artifactr.mcp¶
The mcp extra. See External agents over MCP.
artifactr workspaces over the Model Context Protocol.
External agents (coding assistants, desktop assistants, other services) connect as MCP clients and work in a workspace like any other participant: artifacts are resources, commands are tools, and changes arrive as resource-updated notifications::
mcp = ArtifactrMcp(workspaces, runner, resolve=resolve_client)
app.mount("/mcp", mcp.http_app(streamable_http_path="/"))
# and in the application's lifespan:
async with mcp.lifespan():
yield
The server¶
ArtifactrMcp
¶
ArtifactrMcp(
workspaces: Workspaces,
runner: Runner[Any],
*,
resolve: ResolveClient,
authorize: Authorize | None = None,
name: str = "artifactr",
bus: SubscriptionBus | None = None,
)
An MCP server over artifactr workspaces.
Mount http_app in the application, and run lifespan in the application's
lifespan. Every tool call goes through the same workspace and runner as the other surfaces,
attributed to the client's ExternalAgentActor.
The MCP SDK traces each request itself, through the global tracer provider. The server adds the tenant, workspace and actor to those spans, and has no spans or metrics of its own. Building the SDK's server configures logging for the whole process; this server undoes that, so logging stays the application's.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
workspaces
|
Workspaces
|
Opens tenant-scoped workspaces. |
required |
runner
|
Runner[Any]
|
Carries out every tool's command, once per |
required |
resolve
|
ResolveClient
|
Authenticates each request. |
required |
authorize
|
Authorize | None
|
Whether a client may use a workspace of its tenant: the router's hook, asked
on every tool call, resource read and resource subscription that names a workspace;
allows everything if omitted. A refusal is a tool error, or a resource read or
subscription failing with |
None
|
name
|
str
|
The server's name. |
'artifactr'
|
bus
|
SubscriptionBus | None
|
Where resource-change notifications go; in-process by default. |
None
|
http_app
¶
http_app(**options: Any) -> Starlette
Return the Streamable HTTP app to mount, e.g. at /mcp.
lifespan
async
¶
lifespan() -> AsyncGenerator[None]
Run the HTTP session manager; stop watching workspaces afterwards.
aclose
async
¶
Stop the tasks that turn workspace changes into resource notifications.
ResolveClient
module-attribute
¶
ResolveClient = Callable[
[McpContext],
Awaitable[tuple[TenantId, ExternalAgentActor]],
]
Authenticates an MCP request: returns the client's tenant and actor.
McpContext
¶
McpContext = Context[Any, Request]
The context a ResolveClient receives: the MCP SDK's Context of one request.
Over HTTP, ctx.request_context.request is the Starlette Request the call arrived in, so
an authenticator written for the router's HTTPConnection can take it once it is checked
for None, which it is in process, as in tests. ctx.headers holds its headers.
artifact_uri
¶
artifact_uri(
tenant_id: TenantId,
workspace_id: WorkspaceId,
artifact_id: str,
) -> str
Return an artifact's resource URI.
INSTRUCTIONS
module-attribute
¶
INSTRUCTIONS = "This server is a shared workspace of artifacts that people and agents edit together. Read an artifact before changing it, prefer small precise edits, and pass the version you read so conflicting edits are caught. Some artifact types only accept proposals, which a person reviews. Give each change a command_id of your own, and the same one if you retry it, so that it is made once."