Skip to main content
Glama
MCP Sankhya Community Search Server

MCP Sankhya Community Search Server

by delt4d

SankhyaMCP

MCP (Model Context Protocol) server for the Sankhya ERP Oracle database. Exposes safe SQL execution over multiple named Oracle connections to AI agents via the MCP protocol.

Overview

  • Dynamic multi-connection Oracle support — define any number of named connections via environment variables

  • Read-only tool (execute_query) enforces SELECT/WITH/EXPLAIN only

  • Writable tool (execute_unsafe_query) for DML/DDL — blocked on read-only connections

  • CSV output for SELECT queries; success message for DML/DDL

  • Never raises — all errors returned as "Erro[...]: ..." strings

  • Built with FastMCP and managed with uv

Related MCP server: MCP Sankhya Community Search Server

Prerequisites

  • Python 3.11+

  • uv — install guide

  • No Oracle Client required (uses oracledb thin mode)

  • Oracle database accessible from the machine running the server

Setup

  1. Clone the repository and install dependencies:

uv sync
  1. Configure environment variables in .vscode/mcp.json (copy from the template in this repo — the file is git-ignored):

{
  "servers": {
    "sankhya-mcp": {
      "type": "stdio",
      "command": "${workspaceFolder}/.venv/Scripts/python.exe",
      "args": ["${workspaceFolder}/mcp_server.py"],
      "env": {
        "ORACLE_CONNECTIONS": "teste,producao",
        "ORACLE_TESTE_USER": "your_user",
        "ORACLE_TESTE_PASSWORD": "your_password",
        "ORACLE_TESTE_DSN": "host:port/service_name",
        "ORACLE_PRODUCAO_USER": "your_user",
        "ORACLE_PRODUCAO_PASSWORD": "your_password",
        "ORACLE_PRODUCAO_DSN": "host:port/service_name",
        "ORACLE_PRODUCAO_READONLY": "true",
        "ORACLE_DEFAULT_CONNECTION": "teste"
      }
    }
  }
}
  1. Open the project in VS Code — the MCP panel will detect the server automatically.

Configuring Connections

Connections are defined entirely via environment variables — no code changes required.

1. Declare connection names

ORACLE_CONNECTIONS=teste,producao,SUP

Comma-separated list of names. If omitted, the server falls back to the built-in defaults (teste and producao).

2. Define credentials for each connection

For each name {NAME} declared above, set:

Variable

Required

Description

ORACLE_{NAME}_USER

yes

Oracle username

ORACLE_{NAME}_PASSWORD

yes

Oracle password

ORACLE_{NAME}_DSN

yes

host:port/service_name

ORACLE_{NAME}_SCHEMA

no

Schema prefix for ALTER SESSION SET CURRENT_SCHEMA (default: {NAME} uppercased)

ORACLE_{NAME}_DESCRIPTION

no

Human-readable description shown in list_schemas

ORACLE_{NAME}_READONLY

no

Set "true" to block DML/DDL on this connection

3. Set the default connection (optional)

ORACLE_DEFAULT_CONNECTION=SUP

If omitted, the first connection in ORACLE_CONNECTIONS is used.

Full example (mcp.json env block)

"env": {
  "ORACLE_CONNECTIONS": "teste,SUP",
  "ORACLE_TESTE_USER": "user_teste",
  "ORACLE_TESTE_PASSWORD": "pass_teste",
  "ORACLE_TESTE_DSN": "host:1521/ORCL",
  "ORACLE_TESTE_SCHEMA": "TESTE",
  "ORACLE_TESTE_DESCRIPTION": "Base de teste",
  "ORACLE_SUP_USER": "user_sup",
  "ORACLE_SUP_PASSWORD": "pass_sup",
  "ORACLE_SUP_DSN": "host:1521/SUPORTE",
  "ORACLE_SUP_SCHEMA": "SUPORTE",
  "ORACLE_SUP_DESCRIPTION": "Base de suporte",
  "ORACLE_SUP_READONLY": "true",
  "ORACLE_DEFAULT_CONNECTION": "teste"
}

Available MCP Tools

list_schemas

Lists all available Oracle connections. No parameters. Returns CSV.

Columns: name, schema, description, readonly, is_default

Example response:

name,schema,description,readonly,is_default
teste,TESTE,Base de teste,False,True
producao,SANKHYA,Base de produção,True,False

execute_query

Executes a read-only SQL query (SELECT, CTEs, EXPLAIN PLAN). DML/DDL is rejected.

Parameter

Type

Default

Description

query

str

required

SQL statement (SELECT / WITH / EXPLAIN PLAN)

connection

str

null

Connection name from list_schemas, or null for default

params

dict

null

Bind parameters (:name style)

max_rows

int

500

Maximum rows returned

offset

int

0

Rows to skip before returning results

Returns CSV (with header row) for SELECT queries. Returns "Erro[...]: ..." on failure.

execute_unsafe_query

Executes any SQL including INSERT, UPDATE, DELETE, DDL, and PL/SQL blocks. Blocked on connections where readonly=True.

Same parameters as execute_query. Requires explicit user confirmation before use.

Returns "Sucesso: Comando executado (sem retorno)." for DML/DDL with no result set, or CSV if the statement returns rows.

Example Queries

Always prefix table names with the connection's schema (or rely on ALTER SESSION SET CURRENT_SCHEMA):

-- List recent sales orders
SELECT NUNOTA, DTNEG, CODPARC, VLRNOTA
FROM TGFCAB
WHERE DTNEG >= SYSDATE - 30
ORDER BY DTNEG DESC

-- Check a partner with bind param
SELECT CODPARC, NOMEPARC, CGC_CPF
FROM TGFPAR
WHERE CODPARC = :codparc

Using the MCP tools:

list_schemas                                        → discover connections
execute_query("SELECT ...", "teste")                → read from test DB
execute_query("SELECT ...", "teste", offset=500)    → paginate results
execute_unsafe_query("INSERT ...", "teste")         → write to test DB

Project Structure

mcp_server.py       # FastMCP entry point
src/
  oracle/
    config.py       # ConnectionConfig dataclass + env loading
    query.py        # execute_query() + _is_safe_query() guard
    schemas.py      # list_schemas_info() + list_schemas_csv()
    tools.py        # register_tools(mcp) — wires MCP tools
    __init__.py     # re-exports
tests/
  test_oracle.py    # pytest unit tests

Notes

  • Referencias/ contains reference implementations used during development. It is git-ignored and not part of this project.

  • DML/DDL should only target writable connections (readonly=false).

  • For large result sets, use offset + max_rows to paginate.

Available Tools

12 tools
call_procedureA
Destructive

Call a stored procedure or package procedure via anonymous PL/SQL block. Supports IN parameters only; OUT parameters are not supported. Commits automatically. Only available on writable connections.

Inputs: procedure_name (required), params, connection. Returns: result

create_procedureA
Destructive

Create or replace a procedure, function, or package using a full DDL statement. The statement must start with CREATE. Commits automatically (DDL). Only available on writable connections.

Inputs: procedure_sql (required), connection. Returns: result

create_triggerA
Destructive

Create or replace a trigger using a full DDL statement. The statement must start with CREATE. Commits automatically (DDL). Only available on writable connections.

Inputs: trigger_sql (required), connection. Returns: result

delete_queryA
Destructive

Execute a DELETE statement. Commits automatically. Only available on writable connections (readonly=false in list_schemas). Returns the number of rows deleted.

Inputs: query (required), params, connection. Returns: result

execute_queryA
Read-only

Execute read-only SQL query (SELECT and EXPLAIN PLAN only). CTEs (WITH ... SELECT) accepted. Use list_schemas to see available connections and their readonly status.

Inputs: query (required), offset, params, max_rows, +1 more. Returns: result

execute_unsafe_queryA
Destructive

Execute any SQL statement without restrictions. SELECT returns CSV; DML returns row count. Set auto_commit=false for a dry-run: changes are rolled back after reporting the affected row count. Only available on writable connections.

Inputs: sql (required), params, connection, auto_commit. Returns: result

insert_queryA
Destructive

Insert a single row into a table. Commits automatically. Only available on writable connections (readonly=false in list_schemas). Returns the number of rows inserted.

Inputs: table (required), values (required), connection. Returns: result

list_schemasA
Read-only

List available Oracle connections/schemas with descriptions and readonly status. Use readonly field to determine which tools are available:

  • execute_query: any connection

  • insert_query / update_query / delete_query / call_procedure / create_trigger / set_trigger_status / create_procedure / execute_unsafe_query: readonly=false only.

Inputs: no named parameters. Returns: result

sankhya_call_serviceA

Chama um serviço Sankhya via API REST.

Retorna JSON da resposta incluindo status ('1'=ok, '0'=erro) e responseBody. Use sankhya_list_connections para ver as conexões disponíveis.

Inputs: service_name (required), module, connection, request_body. Returns: result

sankhya_list_connectionsA
Read-only

Lista conexões Sankhya disponíveis com auth_url, base_url e status padrão.

Retorna CSV com colunas: name, description, auth_url, base_url, is_default.

Inputs: no named parameters. Returns: result

set_trigger_statusA
Destructive

Enable or disable a trigger via ALTER TRIGGER name ENABLE/DISABLE. Only available on writable connections.

Inputs: action (required), trigger_name (required), connection. Returns: result

update_queryA
Destructive

Execute an UPDATE statement. Commits automatically. Only available on writable connections (readonly=false in list_schemas). Returns the number of rows updated.

Inputs: query (required), params, connection. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 12 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes: read-only query, insert/update/delete, procedure call, DDL operations, and Sankhya service calls. The catch-all execute_unsafe_query overlaps by design but is explicitly labeled as the unrestricted fallback, so the boundaries are mostly clear.

    Naming Consistency2/5

    SQL tools consistently follow a verb_noun pattern (execute_query, insert_query, create_trigger), but the Sankhya tools reverse the order with a domain prefix (sankhya_call_service, sankhya_list_connections). This mixed convention creates confusion about whether the tool name starts with the action or the domain.

    Tool Count4/5

    12 tools is within the typical well-scoped range. The set covers both Oracle SQL operations and Sankhya service integration, though the presence of both specialized DDL tools and execute_unsafe_query introduces some redundancy.

    Completeness3/5

    The SQL tools cover insert, update, delete, query, procedure/trigger management, and unsafe fallback, but there is no schema discovery tool like list_tables or describe_table. The Sankhya integration is minimal (call service, list connections) and may not cover all necessary service operations.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers