Skip to main content
Glama
Sidrahhh

Company Data MCP Server

by Sidrahhh

Company Data MCP Demo

A multi-source Model Context Protocol (MCP) demo that connects a LangChain/OpenAI chatbot to four company data sources through one read-only MCP server:

  • PostgreSQL

  • MongoDB Atlas

  • Local flat files

  • A private GitHub repository

The chatbot can investigate business records, application logs, operational guidance, and source-code implementation in one workflow.


Architecture

User
  |
  v
chatbot.py
LangChain Agent + OpenAI
  |
  v
MCP Client
  |
  | Streamable HTTP
  v
MCP Server
  |
  +------------------+------------------+------------------+------------------+
  |                  |                  |                  |
  v                  v                  v                  v
PostgreSQL        MongoDB Atlas      Flat Files         GitHub
employees         application_logs   error_codes.csv    payment-service-demo
payments

The MCP server is independent of the chatbot. Any compatible MCP client can connect to it.


Current MCP Tools

PostgreSQL

list_sql_tables
describe_sql_table
query_sql_table

MongoDB

list_mongo_collections
find_mongo_documents

Flat files

list_data_files
read_data_file
search_data_files

GitHub

list_github_repository_files
read_github_repository_file
search_github_repository

The tools are generic but constrained. The server does not expose unrestricted SQL, arbitrary MongoDB commands, unrestricted filesystem access, or GitHub write operations.


Project Structure

company-data-mcp-demo/
|
|-- .env
|-- .env.example
|-- .gitignore
|-- requirements.txt
|-- README.md
|-- chatbot.py
|
|-- data/
|   |-- error_codes.csv
|   |-- notes.txt
|   `-- runbook.json
|
`-- mcp_server/
    |-- __init__.py
    |-- server.py
    |
    `-- connectors/
        |-- __init__.py
        |-- sql_connector.py
        |-- mongo_connector.py
        |-- file_connector.py
        `-- github_connector.py

Prerequisites

Install or have access to:

  • Python

  • PostgreSQL

  • Node.js

  • MongoDB Atlas account

  • OpenAI API key

  • GitHub account

  • VS Code or another editor

Useful checks:

python --version
node --version
npm --version
psql --version

Python Environment

Create a virtual environment:

python -m venv .venv

Activate on Windows CMD:

.venv\Scripts\activate

Activate on PowerShell:

.venv\Scripts\Activate.ps1

Install dependencies:

python -m pip install -r requirements.txt

Validate:

python -m pip check

Expected:

No broken requirements found.

requirements.txt

Use the pinned environment for the MCP/LangChain stack:

# MCP
mcp==1.29.0
langchain-mcp-adapters==0.3.2

# LLM / Agent
langchain==1.3.14
langchain-openai==1.4.0
openai==2.47.0

# Environment variables
python-dotenv==1.2.1

# PostgreSQL
psycopg[binary]==3.3.4

# MongoDB Atlas
pymongo==3.12.0
dnspython>=1.16.0

# GitHub REST API
httpx

This project intentionally remains on MCP 1.x because langchain-mcp-adapters==0.3.2 requires MCP below 2.

The MCP server uses:

from mcp.server.fastmcp import FastMCP

and starts with Streamable HTTP.


Environment Variables

Create .env in the project root:

OPENAI_API_KEY=your_openai_api_key

# PostgreSQL
DB_HOST=localhost
DB_PORT=5432
DB_NAME=company_demo
DB_USER=mcp_user
DB_PASSWORD=your_postgresql_password

# MongoDB Atlas
MONGODB_USER=mongo_mcp_user
MONGODB_PASSWORD=your_mongodb_password
MONGODB_HOST=your_cluster_host.mongodb.net
MONGODB_DB=company_demo

# GitHub
GITHUB_TOKEN=your_fine_grained_github_token
GITHUB_OWNER=your_github_username
GITHUB_REPO=payment-service-demo
GITHUB_BRANCH=main

Create .env.example with placeholders only:

OPENAI_API_KEY=your_openai_api_key_here

DB_HOST=localhost
DB_PORT=5432
DB_NAME=company_demo
DB_USER=mcp_user
DB_PASSWORD=your_postgres_password_here

MONGODB_USER=mongo_mcp_user
MONGODB_PASSWORD=your_mongodb_password_here
MONGODB_HOST=your_cluster_host.mongodb.net
MONGODB_DB=company_demo

GITHUB_TOKEN=your_github_token_here
GITHUB_OWNER=your_github_username
GITHUB_REPO=payment-service-demo
GITHUB_BRANCH=main

Recommended .gitignore:

.env
.venv/
venv/
__pycache__/
*.pyc
*.pyo
*.pyd
.vscode/
.DS_Store
Thumbs.db

Never commit .env.


PostgreSQL Setup

Create the database

Start PostgreSQL and connect as an administrator:

psql -U postgres

Create:

CREATE DATABASE company_demo;

Connect:

\c company_demo

Create the employees table

CREATE TABLE employees (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    department VARCHAR(100),
    role VARCHAR(100),
    email VARCHAR(255)
);

Create the payments table

CREATE TABLE payments (
    id SERIAL PRIMARY KEY,
    employee_id INTEGER REFERENCES employees(id),
    payment_id VARCHAR(100) UNIQUE NOT NULL,
    amount NUMERIC(10,2),
    status VARCHAR(50),
    error_code VARCHAR(50)
);

Insert sample employee data

INSERT INTO employees (
    name,
    department,
    role,
    email
)
VALUES
(
    'Alice',
    'Engineering',
    'Developer',
    'alice@example.com'
),
(
    'Bob',
    'Finance',
    'Analyst',
    'bob@example.com'
),
(
    'Charlie',
    'Security',
    'Security Engineer',
    'charlie@example.com'
);

Verify:

SELECT * FROM employees;

Expected records include:

1 | Alice   | Engineering | Developer
2 | Bob     | Finance     | Analyst
3 | Charlie | Security    | Security Engineer

Insert sample payment data

INSERT INTO payments (
    employee_id,
    payment_id,
    amount,
    status,
    error_code
)
VALUES
(
    1,
    'PAY-001',
    5000.00,
    'FAILED',
    'E109'
),
(
    2,
    'PAY-002',
    2500.00,
    'SUCCESS',
    NULL
),
(
    1,
    'PAY-003',
    1200.00,
    'SUCCESS',
    NULL
);

Verify:

SELECT * FROM payments;

Important demo relationship:

Alice -> PAY-001 -> 5000.00 -> FAILED  -> E109
Bob   -> PAY-002 -> 2500.00 -> SUCCESS
Alice -> PAY-003 -> 1200.00 -> SUCCESS

Create a dedicated read-only PostgreSQL user

Do not use the postgres administrator account from the MCP server.

Create:

CREATE USER mcp_user WITH PASSWORD 'choose_a_strong_password';

Grant database access:

GRANT CONNECT ON DATABASE company_demo TO mcp_user;

Grant schema access:

GRANT USAGE ON SCHEMA public TO mcp_user;

Grant read-only table access:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_user;

Ensure future tables also receive read access:

ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO mcp_user;

Verify read-only behavior

Exit:

\q

Connect as the MCP user:

psql -U mcp_user -d company_demo -h localhost

Reading should work:

SELECT * FROM employees;

A write should fail:

DELETE FROM employees WHERE id = 1;

That failure is expected.


MongoDB Atlas Setup

Create or select a deployment

In MongoDB Atlas:

  • Sign in

  • Create or select a project

  • Create or select a cluster/deployment

  • Wait until it is ready


Configure Network Access

Open the Atlas Network Access area.

Add your current public IP address.

For production, avoid unnecessarily broad network rules such as:

0.0.0.0/0

unless that exposure is intentional.


Create the database and collection

In Atlas Data Explorer create:

Database:
company_demo

Collection:
application_logs

Insert sample application logs

PAY-001

{
  "payment_id": "PAY-001",
  "service": "payment-service",
  "error_code": "E109",
  "message": "Gateway timeout while contacting payment provider",
  "retry_count": 0,
  "severity": "ERROR"
}

PAY-002

{
  "payment_id": "PAY-002",
  "service": "payment-service",
  "message": "Payment completed successfully",
  "retry_count": 0,
  "severity": "INFO"
}

PAY-003

{
  "payment_id": "PAY-003",
  "service": "payment-service",
  "message": "Payment completed successfully",
  "retry_count": 0,
  "severity": "INFO"
}

The important correlation is:

PostgreSQL:
PAY-001 -> FAILED -> E109

MongoDB:
PAY-001 -> Gateway timeout -> retry_count 0

Create a read-only MongoDB database user

Do not use an Atlas admin/database setup account from the MCP application.

Create a new database user:

Username:
mongo_mcp_user

Use password/SCRAM authentication.

Assign:

Role:
read

Database:
company_demo

Avoid broad permissions such as:

atlasAdmin
readWriteAnyDatabase

Test the MongoDB read-only user

Connect using mongosh:

mongosh "mongodb+srv://YOUR_CLUSTER_HOST/" --username mongo_mcp_user

Select:

use company_demo

Reading should work:

db.application_logs.find()

A write should fail:

db.application_logs.insertOne({
    test: "should fail"
})

MongoDB passwords with special characters

If the username or password contains reserved URI characters such as:

@
:
/
?
#
%
&
+

they must be URL encoded.

The connector handles this by encoding credentials before placing them into the MongoDB URI.


Flat-File Setup

Create:

data/

inside the project root.


error_codes.csv

Create:

data/error_codes.csv

Contents:

error_code,meaning,recommended_action
E109,Gateway timeout,Retry up to 3 times with exponential backoff
E201,Invalid account details,Verify account information before retrying
E305,Provider unavailable,Wait and retry later

This provides the documented operational guidance used in the demo.

The key relationship is:

PostgreSQL
PAY-001 -> FAILED -> E109

MongoDB
PAY-001 -> Gateway timeout

Flat file
E109 -> Retry up to 3 times with exponential backoff

notes.txt

Optional:

Payment failures must be investigated using transaction records,
application logs, and documented error handling guidance.

runbook.json

Optional:

{
  "payment_service": {
    "owner": "Payments Team",
    "critical_severity": "ERROR"
  }
}

Supported file types

The current connector supports:

.csv
.json
.txt
.log
.md
.yaml
.yml

The connector is sandboxed to the project's data/ directory and should reject attempts to leave that directory.


GitHub Repository Setup

The GitHub connector reads a separate repository representing the application implementation.

Recommended repository:

payment-service-demo

Keep this repository separate from the MCP server repository.

Example structure:

payment-service-demo/
|
|-- README.md
|
|-- app/
|   |-- __init__.py
|   |-- config.py
|   |-- gateway.py
|   `-- payment.py
|
`-- tests/
    `-- test_payment.py

The demo repository intentionally implements three retry attempts but uses a fixed delay instead of exponential backoff.

That gives the MCP agent a meaningful implementation mismatch to detect.


Repository visibility

For this demo, use:

Private

A private repository proves that the GitHub connector is authenticating successfully rather than simply reading public files.


Create a fine-grained GitHub Personal Access Token

In GitHub:

Settings
-> Developer settings
-> Personal access tokens
-> Fine-grained tokens
-> Generate new token

Configure:

Repository access:
Only select repositories

Select:

payment-service-demo

Grant:

Repository permissions:
Contents -> Read-only

Do not give write permissions.

Copy the generated token and store it only in the MCP project's .env:

GITHUB_TOKEN=your_token_here

Do not place the real token in:

README.md
.env.example
source code
Git commits
chat prompts

GitHub environment configuration

Add:

GITHUB_TOKEN=your_fine_grained_github_token
GITHUB_OWNER=your_github_username
GITHUB_REPO=payment-service-demo
GITHUB_BRANCH=main

to .env.

The GitHub token is used by the MCP server to access the private repository. It is not passed to the LLM.


GitHub connector behavior

The connector:

  • lists approved repository files

  • reads approved source/text files

  • searches approved files for text

  • limits file extensions

  • limits file sizes

  • uses the configured repository and branch

  • performs read-only GitHub operations

No GitHub write, commit, pull-request, merge, or delete functionality is exposed.


Test the GitHub connector directly

Run:

python -m mcp_server.connectors.github_connector

Expected output should include files such as:

README.md
app/__init__.py
app/config.py
app/gateway.py
app/payment.py
tests/test_payment.py

If this works, the following are confirmed:

GitHub PAT
    ->
private repository access
    ->
GitHub REST API
    ->
Python connector

Start the MCP Server

Activate the virtual environment:

.venv\Scripts\activate

Start:

python -m mcp_server.server

The endpoint is:

http://localhost:8000/mcp

Keep this terminal open.


MCP Inspector

Start Inspector in another terminal:

npx @modelcontextprotocol/inspector@latest

Choose:

Transport:
Streamable HTTP

Use:

http://localhost:8000/mcp

Expected tools:

list_sql_tables
describe_sql_table
query_sql_table

list_mongo_collections
find_mongo_documents

list_data_files
read_data_file
search_data_files

list_github_repository_files
read_github_repository_file
search_github_repository

Suggested Inspector Tests

PostgreSQL

List tables:

list_sql_tables

Query Alice:

{
  "table_name": "employees",
  "filter_column": "name",
  "filter_value": "Alice",
  "limit": 20
}

MongoDB

Find PAY-001:

{
  "collection_name": "application_logs",
  "field": "payment_id",
  "value": "PAY-001",
  "limit": 20
}

Flat files

Search:

{
  "query": "E109",
  "max_results": 50
}

Expected match:

E109,Gateway timeout,Retry up to 3 times with exponential backoff

GitHub

List repository files:

list_github_repository_files

Read:

{
  "path": "app/payment.py"
}

Search:

{
  "query": "retry",
  "max_results": 50
}

Useful searches include:

retry
sleep
backoff
timeout
E109

Start the Chatbot

Keep the MCP server running.

In another terminal:

.venv\Scripts\activate
python chatbot.py

The chatbot should discover all 11 MCP tools.

The terminal trace shows:

[AGENT SELECTED TOOL]
Tool: ...

[TOOL RESULT]
Tool: ...
Result: ...

This provides observable tool-selection and tool-result logging.


Main End-to-End Demo

Ask:

Investigate Alice's failed payment,
explain why it failed,
tell me the documented recommended action,
and check whether our payment-service code implements that recommendation.

Expected investigation:

PostgreSQL
   |
   | Alice -> employee id 1
   | PAY-001 -> FAILED -> E109
   v

MongoDB
   |
   | Gateway timeout while contacting payment provider
   | retry_count = 0
   v

Flat files
   |
   | E109
   | Retry up to 3 times with exponential backoff
   v

GitHub
   |
   | Inspect payment-service-demo
   | Three retry attempts implemented
   | Fixed delay implemented
   | Exponential backoff missing
   v

Final grounded answer

Expected conclusion:

Alice's PAY-001 payment failed with error code E109.

The application log shows that the payment service encountered
a gateway timeout while contacting the payment provider.

The documented recommendation for E109 is to retry up to three
times with exponential backoff.

The payment-service implementation does retry up to three times,
but it uses a fixed retry delay instead of exponential backoff.

Therefore, the code only partially implements the documented
E109 remediation guidance.

Grounding Rules

The chatbot may say:

PAY-001 failed.

because PostgreSQL contains that fact.

It may say:

The application logged a gateway timeout.

because MongoDB contains that fact.

It may say:

The documented recommendation is to retry up to three times
with exponential backoff.

because error_codes.csv contains that guidance.

It may say:

The implementation retries three times using a fixed delay.

only after retrieving the relevant GitHub source.

The chatbot should not claim:

The external provider definitely had an outage.

The available evidence only establishes a gateway timeout.

It should not claim:

I retried the payment.

No write/retry tool exists.

It should not claim:

I changed the repository.

The GitHub connector is read-only.


Security Summary

PostgreSQL

Credential:
mcp_user

Database permissions:
read only

The connector also restricts allowed tables and columns.

MongoDB

Credential:
mongo_mcp_user

Role:
read on company_demo

The connector also restricts collections and fields.

Flat Files

Only the approved:

data/

directory is accessible.

GitHub

Credential:
Fine-grained PAT

Repository:
payment-service-demo

Permission:
Contents -> Read-only

No GitHub write operations are exposed.

Secrets

All real credentials belong only in:

.env

Never commit .env.

Rotate any secret immediately if it is accidentally exposed.


Recommended Testing Order

Direct connector test
        |
        v
MCP Inspector
        |
        v
Chatbot

This makes failures easy to isolate:

Connector fails
-> source / credentials / API problem

Connector works but Inspector fails
-> MCP server/tool registration problem

Inspector works but chatbot fails
-> MCP client / agent / prompt problem

Project Status

OpenAI chatbot               DONE
LangChain agent               DONE
MCP server                    DONE
MCP Inspector                 DONE
PostgreSQL connector          DONE
MongoDB Atlas connector       DONE
Flat-file connector           DONE
GitHub repository connector   DONE
Agent/tool trace logging      DONE
Four-source investigation     READY

The current demo supports:

Business records
+
application logs
+
documented remediation
+
source-code verification

through one MCP server.