Install
$ agentstack add mcp-agentjido-jido-mcp ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README — it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Jido.MCP
[](https://hex.pm/packages/jidomcp) [](https://hexdocs.pm/jidomcp/) [](https://github.com/agentjido/jidomcp/actions/workflows/ci.yml) [](https://github.com/agentjido/jidomcp/blob/main/LICENSE) [](https://jido.run) [](https://jido.run/ecosystem) [](https://jido.run/discord)
jido_mcp integrates MCP servers into the Jido ecosystem using anubis_mcp directly.
Features
- Shared pooled MCP clients per configured endpoint
- Consume-side API for MCP tools/resources/prompts
- Jido actions + plugin routes for signal-driven usage
- Jido.AI runtime tool sync (MCP tools -> proxy
Jido.Actions) - MCP server bridge (
use Jido.MCP.Server) with explicit allowlists
Installation
def deps do
[
{:jido_mcp, "~> 0.1"}
]
end
Endpoint Configuration
config :jido_mcp, :endpoints,
github: %{
transport: {:streamable_http, [base_url: "http://localhost:8080", mcp_path: "/mcp"]},
client_info: %{name: "my_app", version: "1.0.0"},
protocol_version: "2025-06-18",
capabilities: %{},
timeouts: %{request_ms: 30_000}
},
local_fs: %{
transport: {:stdio, [command: "uvx", args: ["mcp-server-filesystem"]]},
client_info: %{name: "my_app", version: "1.0.0"}
}
Supported transports in v1:
{:stdio, keyword()}for shell/command-based MCP servers{:shell, keyword()}as an alias normalized to:stdio{:sse, keyword()}for legacy HTTP+SSE servers using protocol2024-11-05{:streamable_http, keyword()}for MCP2025-03-26/2025-06-18, including optional SSE streaming via Anubis':enable_sseoption
For Streamable HTTP, :url or a :base_url containing a non-root path is normalized to Anubis' :base_url + :mcp_path option shape.
Endpoint config may also be loaded through an MFA callback:
config :jido_mcp, :endpoints, {MyApp.MCPConfig, :endpoints, []}
The callback must return a map/keyword endpoint declaration or {:ok, endpoints}.
Runtime endpoints can be registered after application start:
{:ok, endpoint} =
Jido.MCP.Endpoint.new(:github, %{
transport: {:streamable_http, [base_url: "http://localhost:8080", mcp_path: "/mcp"]},
client_info: %{name: "my_app", version: "1.0.0"}
})
{:ok, ^endpoint} = Jido.MCP.register_endpoint(endpoint)
Runtime registration is process-local, rejects duplicate endpoint ids, and starts the MCP client only when the endpoint is first used.
Runtime Endpoint Lifecycle
{:ok, endpoint} =
Jido.MCP.Endpoint.new(:runtime_demo, %{
transport: {:streamable_http, [base_url: "http://localhost:8080/mcp"]},
client_info: %{name: "my_app"}
})
{:ok, ^endpoint} = Jido.MCP.register_endpoint(endpoint)
{:ok, tools} = Jido.MCP.list_tools(:runtime_demo)
{:ok, _removed} = Jido.MCP.unregister_endpoint(:runtime_demo)
For config changes at runtime, unregister then register the updated endpoint.
Consume MCP APIs
{:ok, tools} = Jido.MCP.list_tools(:github)
{:ok, called} = Jido.MCP.call_tool(:github, "search_issues", %{"query" => "label:bug"})
{:ok, resources} = Jido.MCP.list_resources(:github)
{:ok, content} = Jido.MCP.read_resource(:github, "repo://owner/name/README")
{:ok, prompts} = Jido.MCP.list_prompts(:github)
{:ok, prompt} = Jido.MCP.get_prompt(:github, "release_notes", %{"version" => "1.2.0"})
All calls return normalized envelopes:
- success:
%{status: :ok, endpoint: atom(), method: String.t(), data: map(), raw: ...} - error:
%{status: :error, endpoint: atom(), type: ..., message: String.t(), details: ...}
Jido Actions + Plugin
Actions
Jido.MCP.Actions.ListToolsJido.MCP.Actions.CallToolJido.MCP.Actions.ListResourcesJido.MCP.Actions.ListResourceTemplatesJido.MCP.Actions.ReadResourceJido.MCP.Actions.ListPromptsJido.MCP.Actions.GetPromptJido.MCP.Actions.RegisterEndpointJido.MCP.Actions.RefreshEndpointJido.MCP.Actions.UnregisterEndpointJido.MCP.Actions.SetDefaultEndpoint
Plugin
defmodule MyApp.Agent do
use Jido.Agent,
name: "assistant",
plugins: [
{Jido.MCP.Plugins.MCP,
%{
default_endpoint: :github,
allowed_endpoints: [:github, :local_fs]
# or allowed_endpoints: :all
}}
]
end
allowed_endpoints defaults to [] (deny-all) when omitted. Set it to :all to allow all currently configured/runtime-registered endpoints.
Signal routes:
mcp.tools.listmcp.tools.callmcp.resources.listmcp.resources.templates.listmcp.resources.readmcp.prompts.listmcp.prompts.getmcp.endpoint.registermcp.endpoint.refreshmcp.endpoint.unregistermcp.endpoint.default.set
To update the plugin default endpoint at runtime, emit mcp.endpoint.default.set with %{endpoint_id: "github"} (or nil/omitted to clear).
Jido.AI Sync
Jido.MCP.JidoAI.Actions.SyncToolsToAgent discovers remote tools and creates proxy Jido.Action modules, then registers them on a running Jido.AI.Agent.
Jido.MCP.JidoAI.Actions.UnsyncToolsFromAgent removes previously synced proxies.
Tool sync uses deterministic MCP readiness: endpoint calls wait on Anubis.Client.await_ready/2 before executing.
Plugin route support:
mcp.ai.sync_toolsmcp.ai.unsync_tools
Host Runtime Orchestration (Signals)
Host projects are expected to orchestrate runtime endpoint lifecycle and tool sync explicitly using plugin signals.
Recommended signal sequences:
- Register endpoint then sync tools
mcp.endpoint.registermcp.ai.sync_tools
- Refresh endpoint then resync tools
mcp.endpoint.refreshmcp.ai.sync_tools(withreplace_existing: true)
- Unsync tools before unregistering endpoint
mcp.ai.unsync_toolsmcp.endpoint.unregister
Example signal payloads:
# mcp.endpoint.register
%{
endpoint_id: "runtime_demo",
endpoint: %{
transport: {:streamable_http, [base_url: "http://localhost:8080/mcp"]},
client_info: %{name: "my_app"}
}
}
# mcp.ai.sync_tools
%{
endpoint_id: "runtime_demo",
agent_server: :my_ai_agent,
replace_existing: true,
prefix: "mcp_"
}
# mcp.ai.unsync_tools
%{endpoint_id: "runtime_demo", agent_server: :my_ai_agent}
# mcp.endpoint.unregister
%{endpoint_id: "runtime_demo"}
Expose Jido As MCP Server
Server module
defmodule MyApp.MCPServer do
use Jido.MCP.Server,
name: "my-app",
version: "1.0.0",
publish: %{
tools: [MyApp.Actions.SearchIssues],
resources: [MyApp.MCP.Resources.ReleaseNotes],
prompts: [MyApp.MCP.Prompts.CodeReview]
}
end
Publication is explicit allowlist only.
Supervision
children =
Jido.MCP.Server.server_children(MyApp.MCPServer,
transport: :streamable_http
)
Router (streamable HTTP)
forward "/mcp", Anubis.Server.Transport.StreamableHTTP.Plug,
Jido.MCP.Server.plug_init_opts(MyApp.MCPServer)
Resource and Prompt Behaviours
Jido.MCP.Server.ResourceJido.MCP.Server.Prompt
Implement those behaviours for items listed in publish.resources and publish.prompts.
Testing
mix test
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: agentjido
- Source: agentjido/jido_mcp
- License: Apache-2.0
- Homepage: https://jido.run/ecosystem/jido_mcp
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.