spakky-mcp
spakky-mcp is the Spakky Agent connector for external MCP servers.
It does one thing: connect MCP servers selected at run time and make their tools callable by the agent. It does not build MCP servers, and it does not expose an agent's own tools as an MCP server.
When to use it
Use this plugin when an agent service needs to attach MCP servers supplied by the developer, the service, or the end user:
- a configured company MCP server,
- a tenant-specific remote MCP endpoint,
- a user-connected GitHub/Linear/search MCP server,
- a per-run inline MCP server declaration.
The MCP server itself can be implemented with FastMCP, the official MCP SDK, or any compatible server implementation.
Install
uv add spakky-mcp
# or through the agent bundle
uv add "spakky[agent]"
Loading the plugin registers McpClient as IAgentRunnerFactory. Inbound adapters such as AG-UI and A2A can keep using the runner factory; MCP servers join the run through RunAgentInput.metadata.
Configure servers
Configured servers use the SPAKKY_MCP__ settings prefix.
export SPAKKY_MCP__SERVERS='[
{"name": "weather", "transport": "stdio", "command": "weather-mcp-server"}
]'
| Setting | Meaning | Default |
|---|---|---|
SPAKKY_MCP__SERVERS |
JSON array of external MCP server declarations | [] |
SPAKKY_MCP__CONNECT_TIMEOUT_SECONDS |
MCP connection timeout in seconds | 30.0 |
Server fields:
| Field | Meaning |
|---|---|
name |
Unique server name for one run. It cannot contain __. |
transport |
stdio or streamable_http |
command, args, env |
stdio server process command, arguments, and environment |
url |
streamable HTTP MCP endpoint |
auth.headers |
Static HTTP headers |
auth.bearer_token_env |
Environment variable containing a bearer token |
auth.oauth_client_credentials |
OAuth2 client-credentials token request config |
call_timeout_seconds |
Per-tool call timeout. Default 60.0 |
Runtime selection
At run time, pass configured server names or inline declarations through RunAgentInput.metadata["mcp"]["servers"].
from spakky.agent import IAgentRunnerFactory, RunAgentInput
async def run_with_user_mcp(factory: IAgentRunnerFactory, agent: object) -> None:
run_input = RunAgentInput(
state_id="run-1",
instruction="answer with external tools",
metadata={"mcp": {"servers": ["weather"]}},
)
async with factory.open_runner(agent, run_input=run_input) as runner:
async for item in runner.run(run_input):
...
Inline server declarations support user self-service connections:
RunAgentInput(
state_id="run-2",
instruction="inspect issue status",
metadata={
"mcp": {
"servers": [
{
"name": "tenant-linear",
"transport": "streamable_http",
"url": "https://tenant.example.com/mcp",
"auth": {"bearer_token": access_token},
}
]
}
},
)
Production services usually implement IMcpRuntimeServerResolver so a request carries stable connection IDs, while the server loads URLs and credentials from a DB or vault. Register that resolver as a Pod and bind it over the default resolver:
from spakky.core.application.application import SpakkyApplication
from spakky.core.application.plugin import Plugin
from spakky.plugins.mcp import IMcpRuntimeServerResolver
PLUGIN_NAME = Plugin(name="my-mcp-connections")
def initialize(app: SpakkyApplication) -> None:
app.add(UserMcpResolver)
app.container.bind_to_type(IMcpRuntimeServerResolver, UserMcpResolver)
Browser users should generally be allowed to add streamable_http endpoints, not arbitrary stdio commands.
AG-UI maps forwardedProps.mcp into the same metadata shape. A2A maps the data part mcp object into the same shape.
Lazy tool search
MCP servers can expose many tools. spakky-mcp does not push every external tool schema into the initial model request. The model sees only two MCP meta-tools:
| Tool | Purpose |
|---|---|
mcp_search_tools |
Search tools available from the MCP servers attached to this run. |
mcp_call_tool |
Call one tool returned by mcp_search_tools. |
External tool names are returned by search as <server_name>__<tool_name>. For example, weather server tool forecast becomes weather__forecast.
This keeps large MCP toolsets from polluting the model context while still letting the model discover and invoke the tools it needs.
When mcp_call_tool requires human approval, the approval request names the selected external MCP tool and includes the selected arguments in metadata.
Development checks
Run package checks from this package directory:
uv run ruff format .
uv run ruff check .
uv run --project ../.. pyrefly check --disable-project-excludes-heuristics --min-severity warn --no-progress-bar --output-format min-text
uv run pytest
License
MIT License
Metadata
Release files for spakky-mcp 8.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| spakky_mcp-8.2.0.tar.gz | 15.4 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| spakky_mcp-8.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.1 kB
Release files / spakky_mcp-8.2.0.tar.gz
| Download URL | spakky_mcp-8.2.0.tar.gz |
|---|---|
| Size | 15.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
08850362856b35b61fd9b0cd4249f96b6a94a624310dbfa82023034ab8474518
|
|
BLAKE2b-256 checksum How to use checksums |
796744d11132b9ffe1ef58a6676b7f9655062b4603c156c256e286f7d64fba9b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logRelease files / spakky_mcp-8.2.0-py3-none-any.whl
| Download URL | spakky_mcp-8.2.0-py3-none-any.whl |
|---|---|
| Size | 18.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9e7345e23ee7d0d578aa787c09d226acc4247ecf6a73be4614f7a86bce966bf9
|
|
BLAKE2b-256 checksum How to use checksums |
bd69fbddbd24e7c5d5a20ccf646aa515562608250f968a798a814bc6358171b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logSecurity for spakky-mcp 8.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for spakky_mcp-8.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.