All five policies live in packages/mcp/policies/ in the repo. Pick the upstream that matches yours, save the file, and run:
npx -y @euno/mcp validate ./euno.policy.yaml
npx -y @euno/mcp proxy --policy ./euno.policy.yaml -- <upstream>
| Policy | Upstream | What it enforces |
|---|---|---|
filesystem.policy.yaml |
@modelcontextprotocol/server-filesystem |
Writes & deletes confined to /data/; executable file types blocked. |
postgres.policy.yaml |
@modelcontextprotocol/server-postgres |
Non-SELECT SQL blocked; credential and audit tables blocked. |
github.policy.yaml |
@modelcontextprotocol/server-github |
Write tools rate-limited to prevent runaway automation. |
slack.policy.yaml |
@modelcontextprotocol/server-slack |
Direct messages restricted to your domain via recipientDomain. |
fetch.policy.yaml |
mcp-server-fetch |
HTTP blocked; userinfo authority blocked; private RFC-1918 and metadata endpoints blocked (lexical SSRF guard). |
Filesystem
Stops the agent from reading sensitive file types and confines writes to a sandbox directory. argumentSchema is a top-level field on the constraint (not a condition); maxCalls uses count.
agentId: filesystem-agent
name: Filesystem Agent
version: 0.1.0
requiredCapabilities:
- resource: read_file
actions: [call]
conditions:
- type: allowedExtensions
extensions: [".csv", ".json", ".txt", ".md"]
- resource: write_file
actions: [call]
argumentSchema:
type: object
required: [path, content]
properties:
path: { type: string, pattern: "/data/.*" }
content: { type: string }
additionalProperties: false
conditions:
- type: allowedExtensions
extensions: [".csv", ".json", ".txt", ".md"]
- type: maxCalls
count: 100
windowSeconds: 60
- resource: list_directory
actions: [call]
Postgres
Reads only, and never from sensitive tables.
agentId: postgres-agent
name: Postgres Read-Only Agent
version: 0.1.0
requiredCapabilities:
- resource: query
actions: [call]
conditions:
- type: allowedOperations
operations: [SELECT, EXPLAIN, SHOW]
- type: allowedTables
tables: [orders, customers, products]
- type: maxCalls
count: 100
windowSeconds: 60
GitHub
Read-heavy, write-rate-limited — protects against runaway issue or PR creation.
agentId: github-agent
name: GitHub Agent
version: 0.1.0
requiredCapabilities:
- resource: search_repositories
actions: [call]
- resource: get_file_contents
actions: [call]
- resource: create_issue
actions: [call]
conditions:
- type: maxCalls
count: 10
windowSeconds: 3600
- resource: create_pull_request
actions: [call]
conditions:
- type: maxCalls
count: 5
windowSeconds: 3600
Slack
Restricts DMs to your own domain — a single recipientDomain condition stops agents from leaking conversations. Channel posting (post_message) addresses Slack channel IDs (e.g. C12345), so a domain gate doesn't apply there.
agentId: slack-agent
name: Slack Agent
version: 0.1.0
requiredCapabilities:
- resource: send_dm
actions: [call]
conditions:
- type: recipientDomain
domains: [company.com]
- type: maxCalls
count: 20
windowSeconds: 3600
- resource: post_message
actions: [call]
conditions:
- type: maxCalls
count: 50
windowSeconds: 3600
Fetch — lexical SSRF guard
Blocks http://, userinfo authorities, and private RFC-1918 ranges including the cloud metadata endpoint 169.254.169.254. The guard is implemented purely with argumentSchema + maxCalls — no custom condition module required. Read it as a defence-in-depth guard rather than a complete SSRF solution — pair with network-level controls in production.
agentId: fetch-agent
name: Fetch Agent
version: 0.1.0
requiredCapabilities:
- resource: fetch
actions: [call]
argumentSchema:
type: object
required: [url]
additionalProperties: false
properties:
url:
type: string
# https only; reject userinfo (user@host), loopback,
# RFC-1918 ranges, and the 169.254/16 metadata endpoint.
pattern: "https://(?!(?:[^/]*@|localhost|127\\.|10\\.|192\\.168\\.|172\\.(?:1[6-9]|2[0-9]|3[01])\\.|169\\.254\\.)).*"
method:
type: string
enum: [GET, HEAD, OPTIONS]
conditions:
- type: maxCalls
count: 60
windowSeconds: 60
@euno/mcp allows tool calls that match no constraint in the manifest — policies restrict only the tools they list. To make denial the default, enumerate every tool the upstream exposes. For tools you can't enumerate, rely on additional controls (network ACLs, the upstream's own auth).