MCP — Database Server
Enforce Scopebound policies on agents using a Database MCP server (PostgreSQL, MySQL, or compatible).
Install
Role template
from scopebound import ScopeboundSDK
from scopebound.adapters.mcp_database import DatabaseMCPAdapter
sb = ScopeboundSDK(base_url="https://your-partner.api.scopebound.ai", api_key="sb-...")
role = DatabaseMCPAdapter.role_template(
name="db-read-agent",
allowed_tables=["invoices", "vendors", "transactions"],
read_only=True, # blocks execute and any DML entirely
max_rows=1000, # enforces DATA_LIMIT_EXCEEDED above this threshold
approval_required=[] # add "execute" here to require HITL on DDL/DML
)
sb.create_role(**role)
Read-only vs read-write
Set read_only=True for analytics agents and reporting pipelines. Only set read_only=False for agents that must write — and always pair with approval_required=["execute"].
Integration
from scopebound.adapters.mcp_database import DatabaseMCPAdapter
adapter = DatabaseMCPAdapter(sb, role_id="db-read-agent")
@server.pre_call
def enforce(tool_name: str, arguments: dict) -> None:
adapter.enforce(tool_name, arguments)
Enforced tools
| Tool | Default policy | Notes |
|---|---|---|
list_tables |
Allow | Returns only allowed_tables |
query |
Allow | Table must be in allowed_tables; rows capped at max_rows |
execute |
Blocked | Blocked entirely when read_only=True; requires approval when read_only=False |
Deny codes
| Code | Trigger |
|---|---|
SCOPE_VIOLATION |
Tool not in role's allowed_tools (e.g. execute on a read-only role) |
PARAMETER_VIOLATION |
Table not in allowed_tables |
DATA_LIMIT_EXCEEDED |
Query limit argument exceeds max_rows |
MCP_SERVER_UNAUTHORIZED |
Agent's JWT does not include database in allowed_mcp_servers |
MCP_TOOL_NOT_FOUND |
Tool name not in Database MCP server's declared manifest |
MCP_ARGUMENT_SCHEMA_VIOLATION |
Required argument (table or query) missing from call |
Example: enforce row limit
from scopebound import ScopeboundDenyError
try:
adapter.enforce("query", {"table": "invoices", "limit": 50000})
except ScopeboundDenyError as e:
print(e.deny_code) # DATA_LIMIT_EXCEEDED
print(e.reason) # "limit 50000 exceeds max_rows 1000"
Example: read-write agent with HITL on execute
role = DatabaseMCPAdapter.role_template(
name="db-write-agent",
allowed_tables=["invoices"],
read_only=False,
approval_required=["execute"]
)
sb.create_role(**role)
adapter = DatabaseMCPAdapter(sb, role_id="db-write-agent")
from scopebound import ScopeboundPendingError
try:
adapter.enforce("execute", {"query": "UPDATE invoices SET status='paid' WHERE id=42"})
except ScopeboundPendingError as e:
status = sb.get_approval(e.approval_id)
# Poll until approved or expired
Direct endpoint
curl -X POST https://your-partner.api.scopebound.ai/v1/mcp/enforce \
-H "X-Scopebound-API-Key: sb-your-key" \
-H "Content-Type: application/json" \
-d '{
"jwt": "your-session-jwt",
"tool_name": "query",
"arguments": {"table": "invoices", "limit": 100},
"mcp_server": "database",
"mcp_tool_schema": {"required": ["table"]}
}'