mcp-server
Click on "Deploy 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-serverWhat's the sales summary for this quarter?"
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-server — tenant-safe, read-only
A Model Context Protocol server exposing operational tools over a multi-tenant dataset to any MCP client, with the tenant bound server-side and never present in the published tool schema.
The argument
An MCP server publishes its tool schema to whatever client connects — Claude Desktop, an IDE, a third-party agent. That makes the schema a trust boundary, and it changes the calculus compared to an agent you own end to end.
If a tool took a company parameter, tenant selection would be delegated to a
model on the other side of the connection: one you did not write, cannot audit,
and whose version can change without telling you. No prompt on your side
constrains it, because the prompt lives over there.
So the tenant is not a parameter. It is read once, at process start, from the server's own configuration:
TENANT = resolve_tenant() # from MCP_TENANT_ID; fails hard if unsetCross-tenant access is not "unlikely" or "blocked by instructions" — there is no argument in which to express it. That is the entire design, and everything below exists to prove it holds rather than assert it.
This matches how MCP is actually deployed: one server process per user, launched by the client with its own configuration. Identity belongs to that config, not to the conversation.
Related MCP server: Sales Analytics MCP Server
Verified, not asserted
MCP_TENANT_ID=acme python scripts/check_isolation.py # 5 properties
python scripts/check_e2e.py # real stdio handshakecheck_isolation.py asserts, against the running server:
# | Property |
1 | No published tool exposes a tenant-like parameter ( |
2 | Every tool is annotated |
3 | Executing every published tool leaks no other tenant's canary |
4 | Injecting |
5 | Without |
Check 3 enumerates whatever the server publishes and builds arguments from each schema, rather than calling a hardcoded list. A hardcoded list would silently skip exactly the tool someone adds later — which is the case worth catching.
check_e2e.py starts the server as a subprocess and drives it through
initialize → list_tools → call_tool over stdio: proof it speaks the protocol,
not just that the Python objects behave.
The checks are themselves checked
MCP_UNSAFE_MODE=1 publishes a deliberately broken tool that accepts company
and honours it. The isolation check must go red under it:
MCP_TENANT_ID=acme MCP_UNSAFE_MODE=1 python scripts/check_isolation.py
# FAIL no tool exposes a tenant parameter -> list_orders_unsafe.company
# FAIL no output contains another tenant's canary -> leaked: ['globex']A guard that has never gone red has not been shown to detect anything. Shipping the broken variant is what makes the green run mean something.
Run it
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
MCP_TENANT_ID=acme python -m server.main # stdioIn an MCP client (Claude Desktop and similar), register one process per tenant:
{
"mcpServers": {
"acme-ops": {
"command": "/path/to/.venv/bin/python",
"args": ["-m", "server.main"],
"cwd": "/path/to/mcp-server",
"env": { "MCP_TENANT_ID": "acme" }
}
}
}Tools
All read-only. None takes a tenant argument.
Tool | Returns |
| Order count and total for a date range |
| Orders with status |
| Customers ranked by total spend |
Structure
mcp-server/
├── server/
│ ├── tenant.py # the only place a tenant is decided
│ ├── data.py # synthetic multi-tenant dataset with per-tenant canaries
│ └── main.py # MCP server; tools + the gated unsafe variant
├── scripts/
│ ├── check_isolation.py # the 5 properties above
│ └── check_e2e.py # stdio protocol handshakeThe dataset is fictional so the repo is clonable and runnable as-is.
Scope
This is a portfolio implementation of one pattern, not a product. See
SECURITY.md for what it does and does not cover — notably that
MCP_TENANT_ID stands in for a verified token, which is what a real deployment
would use.
This server cannot be deployed
Maintenance
Related MCP Connectors
- RumboOAuthcom.rumboar
Securely query and analyze business data, dashboards, projections, alerts, and knowledge.
Read-only tools for finding where a small business leaks deals, time, and cash.
Read-only revenue, subscriptions, customers, and experiments tools for ZeroSettle accounts.
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceProvides read-only tools for querying a synthetic e-commerce dataset, including product categories, products, sales data, customer history, and order details.-
- FlicenseNot gradedqualityCmaintenanceProvides read-only access to a sales database, letting LLMs answer analytics questions like revenue by region or top customers via MCP tools.-
- AlicenseNot gradedqualityCmaintenanceExposes read-only PostgreSQL queries as typed MCP tools, enabling natural-language data analysis while keeping raw tables hidden and enforcing safety limits.MIT
- FlicenseAqualityCmaintenanceEnables secure analytics on an SQLite database of an online store via six specialized tools covering schema, customer metrics, product sales, category revenue, period revenue, and order leaders.6-