spakky-mcp¶
spakky-mcp는 외부 MCP server tools를 Spakky Agent run에 연결하는 단방향 adapter입니다.
McpClient가 IAgentRunnerFactory 구현체로 외부 서버 연결 수명주기를 소유합니다. McpRuntimeServerResolver는 configured server 이름과 run-time inline server 선언을 해석하고, descriptor 계층은 발견된 MCP tools를 lazy search/call meta-tools 뒤에 보관합니다.
Public API¶
MCP adapter plugin joining external server tools to Spakky Agents.
MCP_CALL_TOOL_NAME = 'mcp_call_tool'
module-attribute
¶
Model-facing lazy invocation tool for a discovered MCP tool.
MCP_SEARCH_TOOLS_NAME = 'mcp_search_tools'
module-attribute
¶
Model-facing lazy discovery tool for the current run's MCP toolset.
MCP_METADATA_KEY = 'mcp'
module-attribute
¶
RunAgentInput.metadata key carrying runtime MCP connection selectors.
MCP_SERVERS_METADATA_KEY = 'servers'
module-attribute
¶
Nested metadata key carrying server names or inline server declarations.
PLUGIN_NAME = Plugin(name='spakky-mcp')
module-attribute
¶
Plugin identifier for the MCP adapter package.
MCPClient = McpClient
module-attribute
¶
Uppercase-acronym alias for :class:McpClient.
MCPConfig = McpConfig
module-attribute
¶
Uppercase-acronym alias for :class:McpConfig.
MCPHttpClientProvider = McpHttpClientProvider
module-attribute
¶
Uppercase-acronym alias for :class:McpHttpClientProvider.
MCPRuntimeServerResolver = McpRuntimeServerResolver
module-attribute
¶
Uppercase-acronym alias for :class:McpRuntimeServerResolver.
MCPServerAuthConfig = McpServerAuthConfig
module-attribute
¶
Uppercase-acronym alias for :class:McpServerAuthConfig.
MCPServerConfig = McpServerConfig
module-attribute
¶
Uppercase-acronym alias for :class:McpServerConfig.
MCPTransport = McpTransport
module-attribute
¶
Uppercase-acronym alias for :class:McpTransport.
IMcpHttpClientProvider
¶
Bases: ABC
Factory for authenticated HTTP clients used by streamable_http MCP servers.
open_client(server)
abstractmethod
¶
Open an optional HTTP client for one server connection.
McpHttpClientProvider
¶
Bases: IMcpHttpClientProvider
Default declarative HTTP auth provider for remote MCP servers.
open_client(server)
async
¶
Yield a configured HTTP client when the server declares auth headers.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/auth.py
McpClient(config, http_client_provider=None, runtime_server_resolver=None, runner_factory=None)
¶
Bases: IAgentRunnerFactory
Runner factory that joins external MCP tools to an agent runner.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/client.py
open_runner(agent_instance, run_input=None)
async
¶
Yield a runner whose catalog also carries the external MCP tools.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/client.py
McpOAuthClientAuthMethod
¶
Bases: StrEnum
Client authentication method for OAuth2 client-credentials token requests.
McpOAuthClientCredentialsConfig
¶
Bases: BaseModel
OAuth2 client-credentials declaration for an authenticated MCP server.
McpConfig()
¶
Bases: BaseSettings
Settings declaring the external MCP servers an agent consumes.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/config.py
servers = ()
class-attribute
instance-attribute
¶
External MCP servers whose tools join the agent tool catalog.
connect_timeout_seconds = DEFAULT_MCP_CONNECT_TIMEOUT_SECONDS
class-attribute
instance-attribute
¶
Timeout budget for establishing an MCP server connection.
server_by_name(name)
¶
Return the declared server with the given name.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/config.py
McpServerAuthConfig
¶
Bases: BaseModel
HTTP authentication declaration for a remote streamable_http MCP server.
McpServerConfig
¶
Bases: BaseModel
Declaration of one external MCP server the agent consumes tools from.
McpTransport
¶
Bases: StrEnum
Transport an external MCP server is reached over.
LazyMcpToolset
¶
Sentinel owner type for MCP lazy search/call descriptors.
AbstractMcpError
¶
McpCatalogMergeError
¶
McpResponseError
¶
McpServerConfigurationError
¶
McpToolDiscoveryError
¶
McpToolInvocationError
¶
McpTransportError
¶
IMcpRuntimeServerResolver
¶
Bases: ABC
Resolve MCP servers to join for one Agent run.
resolve_servers(agent_instance, run_input)
abstractmethod
¶
Return the MCP server configs selected for this run.
McpRuntimeServerResolver(config)
¶
Bases: IMcpRuntimeServerResolver
Default resolver using configured servers plus RunAgentInput metadata.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/runtime.py
resolve_servers(agent_instance, run_input)
¶
Resolve runtime metadata or all configured servers.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/runtime.py
resolve_http_auth_headers(auth, env=environ)
async
¶
Return HTTP headers for an authenticated streamable_http MCP connection.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/auth.py
build_lazy_mcp_descriptors(external)
¶
Return the two model-visible tools that lazily expose MCP tools.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/descriptor.py
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | |
build_mcp_runner(runner, external)
¶
Build a runner whose catalog carries lazy MCP search/call tools.
The caller supplies an already-open native runner so any request-scoped model
resolver or durable-port assembly has already happened. The agent Pod
metadata is a shared singleton, so its catalog is augmented on a copy.copy.
The actual external MCP descriptors stay hidden behind lazy meta-tools so a
large MCP server does not flood the model request with every tool schema.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/descriptor.py
설정¶
Configuration for connecting external MCP servers to Spakky Agent runs.
McpTransport
¶
Bases: StrEnum
Transport an external MCP server is reached over.
McpOAuthClientAuthMethod
¶
Bases: StrEnum
Client authentication method for OAuth2 client-credentials token requests.
McpOAuthClientCredentialsConfig
¶
Bases: BaseModel
OAuth2 client-credentials declaration for an authenticated MCP server.
McpServerAuthConfig
¶
Bases: BaseModel
HTTP authentication declaration for a remote streamable_http MCP server.
McpServerConfig
¶
Bases: BaseModel
Declaration of one external MCP server the agent consumes tools from.
McpConfig()
¶
Bases: BaseSettings
Settings declaring the external MCP servers an agent consumes.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/config.py
servers = ()
class-attribute
instance-attribute
¶
External MCP servers whose tools join the agent tool catalog.
connect_timeout_seconds = DEFAULT_MCP_CONNECT_TIMEOUT_SECONDS
class-attribute
instance-attribute
¶
Timeout budget for establishing an MCP server connection.
server_by_name(name)
¶
Return the declared server with the given name.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/config.py
validate_unique_server_names(servers)
¶
Reject duplicate MCP server names before runtime selection is ambiguous.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/config.py
Client¶
Connection lifecycle and tool discovery for external MCP servers (issue #416).
An MCP ClientSession is only usable inside its transport context, so the
callables this module binds to descriptors close over a live session and stay
valid only while the connection is open. McpClient.open_runner keeps every
configured server's session open for the duration of the yielded runner, then
tears the connections down on exit.
McpClient(config, http_client_provider=None, runtime_server_resolver=None, runner_factory=None)
¶
Bases: IAgentRunnerFactory
Runner factory that joins external MCP tools to an agent runner.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/client.py
open_runner(agent_instance, run_input=None)
async
¶
Yield a runner whose catalog also carries the external MCP tools.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/client.py
make_mcp_tool_callable(session, raw_tool_name, call_timeout_seconds)
¶
Bind an owner-less async callable that invokes one external MCP tool.
The callable's only parameter is **arguments: the dispatcher's
owner-prefix step skips it (no leading self/cls) and binds the model payload
straight to the keyword arguments forwarded to call_tool. The configured
per-server timeout bounds each call so a hung external tool cannot block the
agent loop indefinitely.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/client.py
connect_server(server, connect_timeout_seconds, http_client=None)
async
¶
Open a server connection and discover its tools as catalog descriptors.
connect_timeout_seconds bounds the initialize handshake (the session
read timeout) so an unresponsive server fails fast instead of hanging the
connection.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/client.py
Runtime Resolution¶
Runtime MCP connection resolution for user/service supplied toolsets.
MCP_METADATA_KEY = 'mcp'
module-attribute
¶
RunAgentInput.metadata key carrying runtime MCP connection selectors.
MCP_SERVERS_METADATA_KEY = 'servers'
module-attribute
¶
Nested metadata key carrying server names or inline server declarations.
IMcpRuntimeServerResolver
¶
Bases: ABC
Resolve MCP servers to join for one Agent run.
resolve_servers(agent_instance, run_input)
abstractmethod
¶
Return the MCP server configs selected for this run.
McpRuntimeServerResolver(config)
¶
Bases: IMcpRuntimeServerResolver
Default resolver using configured servers plus RunAgentInput metadata.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/runtime.py
resolve_servers(agent_instance, run_input)
¶
Resolve runtime metadata or all configured servers.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/runtime.py
Descriptor¶
descriptor 모듈은 McpClient가 발견한 외부 MCP tools를 lazy mcp_search_tools / mcp_call_tool 표면 뒤에 보관하기 위한 내부 정규화 계층입니다. 애플리케이션 코드는 일반적으로 McpClient, McpConfig, IMcpRuntimeServerResolver만 사용합니다. mcp_call_tool approval request는 meta-tool이 아니라 선택된 외부 MCP tool 이름과 arguments를 노출합니다.
Normalize external MCP servers into the agent tool catalog (issue #416).
ADR-0013 §2 keeps core/spakky-agent protocol-neutral and pushes the MCP
library dependency into this adapter plugin. Discovered MCP tools are kept in a
session-local registry and exposed to the model through two lazy meta-tools:
search the MCP toolset, then call one selected tool. This keeps large MCP
servers out of the initial model tool list while preserving the same dispatcher
path for the final invocation.
MCP_SEARCH_TOOLS_NAME = 'mcp_search_tools'
module-attribute
¶
Model-facing lazy discovery tool for the current run's MCP toolset.
MCP_CALL_TOOL_NAME = 'mcp_call_tool'
module-attribute
¶
Model-facing lazy invocation tool for a discovered MCP tool.
ExternalMcpTool
¶
Sentinel owner type for catalog descriptors discovered from MCP servers.
LazyMcpToolset
¶
Sentinel owner type for MCP lazy search/call descriptors.
ExternalMcpToolDescriptor(identity, owner, callable, schema, description=None, metadata=AgentToolMetadata())
dataclass
¶
Bases: AgentToolDescriptor
Descriptor that binds the MCP argument object verbatim to its callable.
The core binder (bind_agent_tool_invocation) reserves top-level args
and kwargs payload keys for its positional/keyword structured-call form.
An external MCP tool may legitimately declare input fields named args or
kwargs; routing such a payload through that heuristic would fail to bind
or drop the field name. MCP tool inputs are always a flat JSON object, so
this descriptor forwards the whole payload as keyword arguments without the
structured-call interpretation, preserving every declared field name.
bind_invocation(payload)
¶
Forward the MCP argument object as keyword arguments verbatim.
LazyMcpCallToolDescriptor(identity, owner, callable, schema, description=None, metadata=AgentToolMetadata())
dataclass
¶
Bases: AgentToolDescriptor
Lazy call descriptor that surfaces the selected external tool to HITL.
approval_context(payload)
¶
Expose the target MCP tool name and arguments to approval requests.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/descriptor.py
prefixed_tool_name(server_name, raw_tool_name)
¶
Return the collision-safe model-facing name for an external tool.
build_external_descriptor(server_name, tool, callable_)
¶
Normalize one discovered MCP tool into a catalog descriptor.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/descriptor.py
build_external_descriptors(server_name, tools, callable_factory)
¶
Normalize all discovered tools of one server into catalog descriptors.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/descriptor.py
merge_external_catalog(native, external)
¶
Return a catalog combining native descriptors with external MCP tools.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/descriptor.py
build_lazy_mcp_descriptors(external)
¶
Return the two model-visible tools that lazily expose MCP tools.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/descriptor.py
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | |
build_mcp_runner(runner, external)
¶
Build a runner whose catalog carries lazy MCP search/call tools.
The caller supplies an already-open native runner so any request-scoped model
resolver or durable-port assembly has already happened. The agent Pod
metadata is a shared singleton, so its catalog is augmented on a copy.copy.
The actual external MCP descriptors stay hidden behind lazy meta-tools so a
large MCP server does not flood the model request with every tool schema.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/descriptor.py
normalize_call_result(result)
¶
Map an MCP tool result into a JSON value for evidence and the model.
Source code in plugins/spakky-mcp/src/spakky/plugins/mcp/descriptor.py
Plugin¶
Plugin initialization for the MCP external server adapter.
initialize(app)
¶
Register MCP configuration and the external-tool runner factory.