vechemoga-mcp-server
Read-only MCP server for VecheMoga, enabling AI assistants to query PostgreSQL, inspect logs, and check API delivery status.
README
vechemoga-mcp-server
An MCP server that lets an AI assistant read VecheMoga's logs, query its database read-only, and inspect what the API actually sent to Loops and Stripe — without leaving the editor.
One server, two deployments, identical tool names. The only difference is where the data comes from:
| local | dev AWS | |
|---|---|---|
| URL | http://localhost:8417/mcp |
https://mcp.dev.vechemoga.bg/mcp |
| Logs from | the Docker socket | CloudWatch Logs |
| Database | the local Postgres container | RDS, as vechemoga_mcp_reader |
| Auth | none (binds to localhost) | Authorization: Bearer … behind a security-group IP allowlist |
| Runs on | VecheMogaLocal's compose stack | the dev-tools EC2 box |
That is MCP_LOG_BACKEND=docker|cloudwatch, one environment variable. It is deliberately
one codebase: Sesame — the system this is ported from — has a local server.py and an AWS
server.py that have drifted into ~1400 and ~1800 lines of largely duplicated tool code.
Do not fork this to add an environment. Add a backend.
Dev only. There is no prod MCP server, on purpose. A bearer token that can
SELECTfrom the production database and read every production log stream is a materially different risk decision, and not one that should arrive as a side effect of this repo.
Tools
Fifteen, all read-only. Tools whose source is not configured in a given deployment are not
registered at all — an assistant that cannot see deploy_status locally will pick another
route, whereas one that calls it and gets an error will not.
PostgreSQL — pg_list_schemas, pg_list_tables, pg_describe_table, pg_query,
pg_migration_status
pg_query takes a single SELECT / WITH … SELECT / EXPLAIN SELECT, adds a LIMIT when
there is none, caps at 200 rows, and runs under SET TRANSACTION READ ONLY with a 10s
statement timeout. That is the second lock, not the first — see Read-only
below. pg_migration_status reads Liquibase's databasechangelog, which answers "did this
environment actually run the migration I merged?"
Logs — api_logs, api_liquibase_logs, web_logs, wiremock_logs, postgres_logs,
pipeline_logs, automation_logs
All take the same four arguments: tail, since, until, grep. grep is applied after
retrieval, so narrowing with since/until beats a large tail. automation_logs earns
its place: a green Allure report can hide a failed Before/After hook, and the CodeBuild
log is the only place that failure is visible.
WireMock — wiremock_list_mappings, wiremock_find_requests
wiremock_find_requests answers did the API actually call Loops, and with what body? —
which CloudWatch cannot, because WireMock's request logging is deliberately switched off so
that verification links never reach a log group. Strictly the read-only subset of the admin
API: no mapping registration, and never /__admin/reset or a DELETE. Parallel
Cucumber workers and manual developers share that service and a global reset takes their
work with it.
Delivery — deploy_status
codepipeline:GetPipelineState across the pipelines, including vechemoga-infra. Answers
"is dev running the commit I think it is?" and "is an infra change sitting at the approval
gate?" It cannot start, approve or retry anything.
Read-only
Worth being precise about, because "the server only sends SELECTs" is not a security property — it is a hope about a program.
- The PostgreSQL role is the guarantee.
vechemoga_mcp_readerholdsGRANT SELECTand nothing else, withdefault_transaction_read_only = on. A bug in this repo cannot write to that database, because the credential it holds cannot. - The security group is the second. It permits a TCP connection from the dev-tools box and the API box. What that connection may do is decided in (1).
- The SQL guard in
pg_queryis the third, and its job is to turn a mistake into a clear error rather than a permission denial.
The build refuses to push if (3) regresses — buildspec-build.yml drives DELETE, UPDATE,
DROP, INSERT and a stacked SELECT 1; DROP TABLE through it and fails if any is accepted.
Why no port 80
The dev-tools security group allows 443 from a handful of named operator addresses and
nothing else. An HTTP-01 or TLS-ALPN-01 ACME challenge must be answerable from Let's
Encrypt's own validation addresses, which are not knowable in advance — either would force a
port open to 0.0.0.0/0 and demote that allowlist from a security-group boundary to an
application-layer matcher.
So Caddy proves the certificate over a Route 53 DNS-01 challenge, which needs no inbound
reachability at all. That is what caddy/Dockerfile is for (xcaddy with
caddy-dns/route53), and the build fails if the plugin is missing rather than letting the
box fall back to a challenge that cannot work.
If certificate issuance fails, fix the Route 53 grant — do not open port 80.
What the server logs
Which tool ran and with which argument names. Never results. A pg_query answer or a
WireMock journal entry would put database rows and verification links into
/vechemoga/dev/mcp-server, where they would then live for 30 days — the exact hazard
WireMock's own request logging is kept off to avoid.
Local development
The image is pulled from ECR by VecheMogaLocal's compose stack. To work on the server itself:
pip install -r requirements.txt
MCP_LOG_BACKEND=docker \
MCP_DOCKER_CONTAINERS='{"api":"docker-api-1","web":"docker-web-1","postgres":"docker-postgres-1","wiremock":"docker-provider-proxy-1"}' \
POSTGRES_HOST=localhost POSTGRES_USER=vechemoga POSTGRES_PASSWORD=vechemoga POSTGRES_SSLMODE=disable \
WIREMOCK_ADMIN_URL=http://localhost:1080 \
python server.py
Then point your editor at http://localhost:8417/mcp. Container names come from
docker compose ps --format '{{.Name}}' in VecheMogaLocal — they carry the compose project
prefix.
Do not test the endpoint with curl. It speaks MCP, not REST; a curl against /mcp
tells you nothing except that TLS and auth work. Validate by asking your assistant to call
a tool, e.g. "list the schemas in the dev database".
Deployment
Two pipelines write to the dev-tools box, and this repo owns the compose file both of them
deploy into — exactly as VecheMogaApi/deploy owns the file the provider-mock pipeline
deploys into today:
| Pipeline | Deploys |
|---|---|
vechemoga-mcp-server |
mcp-server + caddy |
vechemoga-provider-proxy |
provider-proxy (WireMock) |
Source (GitHub main, CodeConnections)
└─▶ Build CodeBuild ARM · buildspec-build.yml
docker build ×2 (server + caddy, native arm64) → smoke checks
→ ECR :<sha12> (only if the checks passed)
└─▶ Deploy CodeBuild · buildspec-deploy.yml → infra/deploy-to-instance.sh
SSM Run Command on the dev-tools box: pull the pinned tags, up, health-check
Deploys are pinned to the git SHA. Rollback is Release change on an older execution, or
IMAGE_TAG=<old-sha> ./infra/deploy-to-instance.sh from a laptop.
The Deploy stage skips green when the box is absent or stopped — it sleeps nightly 23:30–07:45 Europe/Sofia. A pipeline that goes red every evening for a working reason teaches everyone to stop reading it.
One-time, on the box
Both pipelines run docker compose against a checkout of this repo on the box — they
deploy images, they do not copy files. So the checkout has to exist before the first deploy,
exactly as vechemoga-api is cloned onto the API box. Via SSM Session Manager (no SSH):
sudo git clone https://github.com/simo21-ss/vechemoga-mcp-server.git /opt/vechemoga-devtools
sudo chown -R ec2-user:ec2-user /opt/vechemoga-devtools
COMPOSE_DIR is therefore /opt/vechemoga-devtools/deploy — the clone root plus this
directory. It is set by Terraform on both deploy projects rather than left to the
buildspecs, because CodeBuild resolves an environment variable from the build project
definition ahead of the buildspec, and the target box and its compose path have to move
together.
deploy/.env holds the non-secret wiring (the file is not committed; secrets are read from
SSM on the box at deploy time, by the instance role):
cat >> /opt/vechemoga-devtools/.env <<'EOF'
DB_HOST=veche-moga-db-dev.<...>.eu-central-1.rds.amazonaws.com
MCP_HOST=mcp.dev.vechemoga.bg
MCP_ALLOWED_IPS=176.12.9.148/32
MCP_LOG_GROUPS='{"api":"/vechemoga/dev/api","wiremock":"/vechemoga/dev/provider-proxy","web":"/aws/amplify/<app-id>","pipeline":"/vechemoga/cicd/dev/deploy","automation":"/vechemoga/cicd/automation/test"}'
MCP_PIPELINES=vechemoga-api-dev,vechemoga-web-dev,vechemoga-provider-proxy,vechemoga-automation,vechemoga-mcp-server,vechemoga-infra
PROVIDER_PROXY_IMAGE=<account>.dkr.ecr.eu-central-1.amazonaws.com/vechemoga/provider-proxy
EOF
The single quotes around MCP_LOG_GROUPS are load-bearing. infra/deploy-to-instance.sh
sources this file with set -a; . ./.env, and the shell performs quote removal — so an
unquoted {"api":"…"} reaches the container as {api:…}, which is not JSON, and the server
exits at import. Observed on the first real deploy, as a crash loop.
And two SecureStrings, created by hand so their values never enter Terraform state —
/vechemoga/dev/MCP_AUTH_TOKEN and /vechemoga/dev/MCP_DB_PASSWORD, plus the
vechemoga_mcp_reader role. Runbook: VecheMogaInfra README → "Bring up the dev-tools
box".
Infrastructure
The box, its security group, its IAM role, the ECR repositories and the pipeline are
Terraform-managed in VecheMogaInfra (modules/dev-tools, modules/cicd-mcp,
global/ecr.tf). This repo owns only what runs on the box. The design and its rollout are
in VecheMogaInfra/docs/mcp-server-plan.md.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。