MCP Nexus
Allows task and project management via Todoist API through the MCP Nexus middleware.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Nexusbrowse available services"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Nexus
Browse-first MCP middleware — an LLM-friendly nexus for discovering and invoking MCP tools across multiple services.
AI agents use this as a single MCP endpoint to browse, inspect, and call tools from many upstream MCP servers — without flooding their context with every tool schema upfront.
How It Works
Instead of connecting every MCP server directly (and loading all their tool schemas at session start), agents connect to one nexus server and discover tools on demand:
browse_services → [{id: "todoist", name: "Todoist"}, {id: "outlook", ...}]
browse_tools("todoist") → ["todoist__get-task", "todoist__create-task", ...]
search_tools("send email") → [{name: "outlook__search-emails", serviceId: "outlook"}, ...]
get_schemas(["todoist__get-task"]) → [full input schema]
call_tool("todoist__get-task", {id: "123"}) → resultAgents can either browse (list services → list tools) or search (find tools by keyword or semantic similarity across all services at once).
Related MCP server: mcptool
Quick Start
Prerequisites
Node.js 22+
Install & Run
# Install dependencies
npm install
# Copy a config (or create your own)
cp mcp-nexus.example.yaml mcp-nexus.yaml
# Start in dev mode (with hot reload)
npm run dev
# Or with a custom config path and verbose logging
npx tsx src/index.ts --config ./mcp-nexus.example.yaml --verboseVerify It's Running
# Health check
curl http://localhost:8050/healthConfiguration
Create a mcp-nexus.yaml file:
port: 8050
auth:
enabled: false # Set to true and provide a token in production
token: ""
allowedOrigins: # Optional — restrict CORS to these origins when auth is on
- https://openwebui.local
connectors:
httpReuseIdleTimeoutSeconds: 300 # Reap idle upstream HTTP sessions after N seconds
recoveryIntervalSeconds: 30 # Probe failed sources every N seconds (0 = disabled)
search:
type: lexical # "lexical" (keyword matching) or "semantic" (embedding-based)
maxResults: 20
# semantic: # Uncomment to enable semantic search
# provider: built-in # "built-in" (local), "ollama", or "openai-compatible"
# model: Xenova/all-MiniLM-L6-v2
# batchSize: 32
# # For ollama: provider: ollama, baseUrl: http://ollama:11434, model: nomic-embed-text
# # For openai-compatible: provider: openai-compatible, baseUrl: https://api.openai.com, model: text-embedding-3-small, apiKeyEnv: OPENAI_API_KEY
sources:
- id: todoist
name: Todoist
description: Task and project management
transport: http
url: http://todoist-mcp:8081/mcp
filter: ["*"] # Glob patterns — only index matching tools
- id: outlook
name: Outlook
description: Email and calendar
transport: stdio
command: npx
args: ["-y", "@softeria/ms-365-mcp-server"]
env:
API_KEY: "your-key"
preloadedTools:
- search-emails
- list-foldersConfig Reference
Field | Description |
| HTTP port for the MCP endpoint (default: 8050) |
| Require |
| Static bearer token (override via |
| Optional list of origins allowed via CORS when auth is enabled. If omitted, the request |
| Idle timeout before a cached upstream HTTP session is reaped (default: 300) |
| Interval (seconds) for background recovery probes of failed sources. 0 = disabled (default: 30) |
| Search strategy: |
| Max results returned by |
| Embedding provider: |
| Model name (provider-specific; defaults vary by provider) |
| Base URL for |
| Name of env var containing the API key (required for |
| Batch size for embedding generation at index time (default: 32) |
| Where to cache the downloaded model ( |
| Unique identifier for the source (used in namespaced tool names) |
|
|
| Upstream MCP server URL (required for HTTP transport) |
| Executable to spawn (required for stdio transport) |
| Optional glob patterns to curate which tools are indexed |
| Optional array of non-prefixed tool names to surface directly in |
| Optional default response projections, keyed by non-prefixed tool name (see Response Shaping) |
| Directory artefacts are written under. Omit the whole |
| Delete run directories older than this, at startup and daily (default: 14; 0 = never) |
| How long a label keeps resolving to the same run directory (default: 180) |
| Refuse to write a single artefact larger than this (default: 33554432) |
Search
The search_tools tool lets agents find tools by query instead of browsing every service. Two strategies are available, configured at startup via search.type:
Lexical (default)
Keyword matching against tool names and descriptions. Fast, no dependencies. Best for queries like "send email" or "ebay orders" — concise terms that appear in the tool metadata.
search:
type: lexical
maxResults: 20Semantic
Embedding-based similarity search. Understands natural-language intent like "I want to send an email" or "find tools for managing my inbox". Requires an embedding provider.
search:
type: semantic
maxResults: 20
semantic:
provider: built-in # local model, no external dependencies
model: Xenova/all-MiniLM-L6-v2
batchSize: 32
modelCachePath: /app/data/model-cacheEmbedding Providers
Provider | Description | Config |
| Local model via Transformers.js (all-MiniLM-L6-v2, 384d) | No external dependencies. Downloads model on first run. |
| Local Ollama instance (nomic-embed-text, 768d) | Requires |
| Any OpenAI-compatible API (text-embedding-3-small, 1536d) | Requires |
If the semantic provider fails at query time (e.g. Ollama is down), the search engine falls back to lexical automatically. The response includes strategy and fellBackToLexical fields so the agent can tell what happened.
Docker
# Build
npm run docker:build
# Run
docker run -d \
--name mcp-nexus \
-p 8050:8050 \
-v ./mcp-nexus.yaml:/app/mcp-nexus.yaml \
-e MCP_NEXUS_AUTH_TOKEN=your-token \
mcp-nexusOr use the provided Dockerfile directly:
docker build -t mcp-nexus .MCP Tools
The nexus exposes these tools to connected AI agents:
Tool | What it does |
| List all available upstream services with descriptions and tool counts |
| List all tools for a specific service (namespaced names) |
| Search for tools by keyword (lexical) or natural language (semantic) |
| Get input schemas and inferred response shapes for one or more tools |
| Call a tool on an upstream service, optionally trimming the response or writing it to a file |
| Diagnostic — shows index summary, source availability, and error info |
Additionally, any tools listed under preloadedTools on a source will appear directly in the tools/list response alongside the built-in nexus tools — no browsing needed.
Response Shaping
Upstream tools routinely return far more than an agent needs — every field of every record, often pretty-printed. That width lands directly in the agent's context, so the nexus trims it on the way through.
Always applied. Responses are forwarded as the upstream service's own content blocks, with each JSON block re-serialised compactly. This is lossless — nothing is dropped, and blocks that aren't JSON (prose errors, images, embedded resources) pass through untouched. On live eBay responses this alone removes 38–48% of the bytes.
Projections. To trim fields as well, give call_tool a select array of dotted
paths. [*] maps over an array, and the original nesting is preserved:
{
"toolName": "ebay__ebay_get_inventory_items",
"parameters": { "limit": 25 },
"select": ["total", "inventoryItems[*].sku", "inventoryItems[*].product.title"]
}A path matching nothing is returned as an error, not as absent data, so a typo can't be mistaken for a field the service doesn't return. The error carries the tool's response shape so the caller can correct itself.
For tools that are always too wide, set a default under sources[].projections
instead — keyed by the tool's own name, applied to every call, and overridden by an
explicit select. A configured projection whose paths have drifted out of date warns
and skips them rather than failing, since the caller didn't write it.
Discovering paths. Most services declare no outputSchema, so get_schemas
reports a responseShape instead: the leaf paths and types of what the tool last
returned, learned from calls as they pass through. Its size is fixed regardless of
how many records came back. If a tool hasn't been called yet, make one small call
first (most take a limit or pageSize) and the shape will be recorded.
Artefacts
Projections trim a response; artefacts remove it from the conversation altogether.
When a result is only ever going to be aggregated by code — a full orders feed, a
whole catalogue — passing an artefacts label writes it to a file and returns a
receipt instead:
{
"toolName": "ebay__ebay_get_orders",
"parameters": { "limit": 25, "offset": 50 },
"artefacts": "ebay-weekly-review"
}{
"artefact": {
"run": "20260824-161204-ebay-weekly-review",
"dir": "/data/artefacts/20260824-161204-ebay-weekly-review",
"path": "/data/artefacts/20260824-161204-ebay-weekly-review/ebay_get_orders-a3f1c92b.json",
"bytes": 18206,
"records": 25,
"recordPath": "orders",
"shape": ["total: number", "orders[*].lineItems[*].legacyItemId: string", "…"]
}
}The agent then runs code against dir. Nothing about the payload enters its context.
This requires a code executor that can see the same absolute path — mount one volume into both containers at the same location. Read-only on the executor's side is the cleanest arrangement: artefacts are the nexus's output and its input.
artefacts is a label, not a path. The caller names the task; the nexus builds
the directory name from a timestamp and the label reduced to [a-z0-9-], and
resolves it strictly under root. Every call sharing a label lands in one
directory until it has been idle for runIdleMinutes, so a multi-call pull needs no
coordination — and last week's run can never be read as this week's.
Filenames are derived from the tool and a digest of its arguments, so a retried page overwrites itself instead of leaving a duplicate for the aggregation to double-count.
records is the count of the largest top-level array, reported per file so a
caller can check that pages sum to the expected total without opening anything. A
page past the end of a feed reports 0 rather than going missing.
Projections still apply. The context argument for trimming disappears, but the
reason to keep buyer addresses out of a response is not that they are expensive.
select still overrides a configured projection, and shape describes what is
actually in the file — not the wider upstream response, which get_schemas still
reports in full.
Errors are never written to a file. Transport failures, upstream tool errors and
unmatched select paths all come back inline, as they do without a label. If the
write fails, the call returns an error naming the path and errno — the payload is
deliberately not returned instead, since dumping a whole feed into the context is
the failure the caller was avoiding.
Preloaded tools take no artefacts argument (or select), since they are dispatched
with the upstream schema verbatim. A tool wide enough to want either should be
reached through call_tool.
Architecture
AI Agent ──Streamable HTTP──▶ mcp-nexus ──HTTP/stdio──▶ todoist, outlook, ...
│
In-memory index
Session managementTransport: MCP Streamable HTTP (2025-11-05)
Auth: Optional bearer token, with optional CORS origin allowlist
Health:
GET /healthendpoint for monitoring (Uptime Kuma, etc.)HTTP connection reuse: keep-alive sessions per source, reaped after an idle timeout
Project Structure
src/
index.ts Entry point with CLI args
config.ts YAML loader with Zod validation
types.ts Shared types and interfaces
logger.ts Structured logger
namespace.ts Tool name namespacing (<sourceId>__<toolName>)
glob-utils.ts Glob pattern matching for tool filtering
indexer.ts Startup index — fetches tools/list from all sources
artefacts.ts Run directories, artefact writing, retention
recovery.ts Background recovery probes for failed sources
nexus-server.ts MCP server — tool definitions and request handling
sources/
http-source.ts HTTP transport client (Streamable HTTP)
stdio-source.ts Stdio transport client (subprocess, JSON-RPC)
search/
index.ts SearchEngine — strategy dispatch + fallback
types.ts Search config, result, and provider interfaces
lexical-search.ts Keyword matching (token-based scoring)
semantic-search.ts Embedding similarity search
providers/
builtin.ts Transformers.js (all-MiniLM-L6-v2, local)
ollama.ts Ollama embedding API (nomic-embed-text)
openai.ts OpenAI-compatible embedding APIScripts
Command | Description |
| Run with hot reload via |
| Run without watch |
| Compile TypeScript to |
| Build Docker image |
| Run Docker container |
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
One MCP endpoint for Claude, GPT & Gemini: 100+ tools + no-code connectors + agent workers.
The Remote MCP server acts as a standardized bridge between LLM applications (like Claude, ChatGPT, and Cursor) and external services, enabling AI agents to access external tools and resources. Its primary capability is providing a centralized search tool to discover other MCP servers and their respective tools. Unlike local implementations, it runs remotely with OAuth authentication and permission controls for security.
Pay-per-use tool marketplace for AI agents. Search, price-check, and call APIs via MCP.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP aggregator that consolidates multiple MCP servers behind a single interface with just 3 tools (search, get details, execute), reducing context pollution for AI agents by avoiding direct exposure of numerous tool schemas.212MIT
- AlicenseNot gradedqualityNot gradedmaintenanceA drop-in MCP proxy that aggregates multiple backend servers into two meta-tools for efficient tool discovery and execution. It enables AI clients to access hundreds of tools while minimizing context window usage through searchable indexing.1-
- AlicenseNot gradedqualityDmaintenanceEnterprise-grade dynamic MCP proxy that eliminates token bloat by lazy-loading tool schemas based on semantic intent, enabling efficient orchestration of multiple backend tools from a single endpoint.MIT
- AlicenseNot gradedqualityCmaintenanceA proxy MCP server that manages multiple upstream MCP servers by grouping them and loading tool schemas on-demand, reducing LLM context usage.2,79851MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Aidan-Kay/mcp-nexus'
If you have feedback or need assistance with the MCP directory API, please join our Discord server