Skip to main content
Glama
README.md
# MCP Setup Server

A modular [Model Context Protocol](https://modelcontextprotocol.io) server that
exposes integration "setup" tools to an MCP client (Claude Desktop, Claude Code,
etc.). Each integration lives in its own module, so you can keep adding
integrations (Redash, Jenkins, ...) without touching the others.

## Layout

```
server.py                  # entry point: creates FastMCP, registers integrations
integrations/
  __init__.py
  environment.py           # shared MCP_ENV / env-var resolution helpers
  github.py                # GitHub
  redash.py                # Redash
  jenkins.py               # Jenkins
  figma.py                 # Figma
  jira.py                  # Jira (Atlassian Cloud)
  confluence.py            # Confluence (Atlassian Cloud)
  teams.py                 # Microsoft Teams (Graph)
  datadog.py               # Datadog
  pagerduty.py             # PagerDuty
  slack.py                 # Slack
  presto.py                # Presto / Trino
```

Each integration module exposes a `register(mcp)` function that attaches its
tools. Every integration reads its own credentials from environment variables,
and only at the moment a tool is called — so you can configure just the
integrations you use and leave the rest unset.

## Integrations & required env vars

| Integration | Env vars | Tools |
|-------------|----------|-------|
| GitHub | `GITHUB_TOKEN` | 21 |
| Redash | `REDASH_URL`, `REDASH_API_KEY` | 26 |
| Jenkins | `JENKINS_URL`, `JENKINS_USER`, `JENKINS_API_TOKEN` | 19 |
| Figma | `FIGMA_TOKEN` | 14 |
| Jira | `JIRA_URL`, `JIRA_API_TOKEN` (+ `JIRA_EMAIL` for Cloud) | 18 |
| Confluence | `CONFLUENCE_URL`, `CONFLUENCE_EMAIL`, `CONFLUENCE_API_TOKEN` | 13 |
| Teams | `TEAMS_ACCESS_TOKEN` | 16 |
| Datadog | `DATADOG_API_KEY`, `DATADOG_APP_KEY`, `DATADOG_SITE` | 17 |
| PagerDuty | `PAGERDUTY_API_TOKEN`, `PAGERDUTY_FROM_EMAIL` | 17 |
| Slack | `SLACK_BOT_TOKEN` | 17 |
| Presto | `PRESTO_HOST`, `PRESTO_PORT`, `PRESTO_USER`, `PRESTO_CATALOG`, `PRESTO_SCHEMA` | 8 |

See `.env.example` for where to obtain each credential. **186 tools total.**

**Jira** auto-detects the deployment from `JIRA_URL`: Atlassian **Cloud**
(`*.atlassian.net`) uses email + API-token basic auth and REST v3; **Server /
Data Center** uses a Personal Access Token (Bearer) and REST v2, with
`JIRA_EMAIL` left unset. The tools are identical across both.

## Tools

### GitHub

| Tool | Description |
|------|-------------|
| `github_whoami` | Verify the token and show the authenticated user |
| `github_list_repos` | List your repositories |
| `github_get_repo` | Get details for one repository |
| `github_create_repo` | Create a new repository |
| `github_list_issues` | List issues for a repository |
| `github_create_issue` | Open a new issue |
| `github_search_code` | Search code across GitHub |

#### GitHub — pull requests

| Tool | Description |
|------|-------------|
| `github_list_pull_requests` | List pull requests for a repository |
| `github_create_pull_request` | Open a new pull request |
| `github_get_pull_request` | Get full details for one PR |
| `github_update_pull_request` | Edit title / body / state / base branch |
| `github_list_pull_request_files` | List changed files with add/delete counts |
| `github_list_pull_request_commits` | List the commits in a PR |
| `github_comment_on_pull_request` | Add a conversation-tab comment |
| `github_list_pull_request_conversation_comments` | Fetch conversation-tab comments |
| `github_add_pull_request_review_comment` | Add an inline comment on a diff line |
| `github_list_pull_request_review_comments` | Fetch inline diff comments |
| `github_create_pull_request_review` | Submit a review (approve / request changes / comment) |
| `github_list_pull_request_reviews` | Fetch submitted reviews |
| `github_request_pull_request_reviewers` | Request reviewers (users / teams) |
| `github_merge_pull_request` | Merge a PR (merge / squash / rebase) |

### Redash

| Tool | Description |
|------|-------------|
| `redash_connectivity` | Verify the URL + API key and show the current user |
| **Queries** | |
| `redash_list_queries` | List queries (optional search) |
| `redash_get_query` | Get a query's SQL, options and visualizations |
| `redash_create_query` | Create a query (optionally published) |
| `redash_update_query` | Update an existing query's fields / publish state |
| `redash_fork_query` | Duplicate a query |
| `redash_archive_query` | Archive (soft-delete) a query |
| `redash_run_query` | Execute a saved query and return result rows |
| `redash_execute_adhoc_query` | Execute ad-hoc SQL against a data source (not saved) |
| **Data sources** | |
| `redash_list_data_sources` | List data sources |
| `redash_get_data_source` | Get one data source |
| `redash_get_data_source_schema` | Get tables/columns for a data source |
| **Visualizations** | |
| `redash_create_visualization` | Create a visualization for a query |
| `redash_update_visualization` | Update a visualization |
| `redash_delete_visualization` | Delete a visualization |
| **Dashboards** | |
| `redash_list_dashboards` | List dashboards |
| `redash_get_dashboard` | Get a dashboard with its widgets |
| `redash_create_dashboard` | Create a dashboard |
| `redash_update_dashboard` | Rename / publish / re-layout a dashboard |
| `redash_delete_dashboard` | Delete a dashboard |
| `redash_add_widget_to_dashboard` | Add a chart or textbox widget |
| **Alerts** | |
| `redash_list_alerts` | List alerts |
| `redash_get_alert` | Get one alert |
| `redash_create_alert` | Create a threshold alert on a query |
| `redash_delete_alert` | Delete an alert |
| **Users** | |
| `redash_list_users` | List users |

### Jenkins

| Tool | Description |
|------|-------------|
| `jenkins_connectivity` | Verify the URL + credentials and show instance info |
| **Jobs & folders** | |
| `jenkins_list_jobs` | List jobs at root or inside a folder |
| `jenkins_get_job` | Job details: recent builds, health, buildable |
| `jenkins_get_job_parameters` | List a job's build parameters |
| `jenkins_get_job_config` | Get a job's raw `config.xml` |
| `jenkins_create_job` | Create a job from a `config.xml` string |
| `jenkins_update_job_config` | Replace a job's `config.xml` |
| `jenkins_copy_job` | Copy a job to a new name |
| `jenkins_create_folder` | Create a folder (Folders plugin) |
| `jenkins_delete_job` | Delete a job or folder |
| `jenkins_enable_job` / `jenkins_disable_job` | Enable / disable a job |
| **Builds** | |
| `jenkins_trigger_build` | Trigger a build (optional parameters); handles CSRF crumb |
| `jenkins_get_build` | Info for a specific build (result, duration, causes) |
| `jenkins_get_last_build` | Info for the most recent build |
| `jenkins_get_build_log` | Console log (optionally just the tail) |
| `jenkins_stop_build` | Abort a running build |
| **Queue** | |
| `jenkins_get_queue` | List items waiting in the build queue |
| `jenkins_get_queue_item` | Status of a queue item (did it start a build?) |

### Figma

| Tool | Description |
|------|-------------|
| `figma_whoami` | Verify the token and show the current user |
| `figma_get_file` | Get a file's metadata and pages |
| `figma_get_file_nodes` | Fetch specific nodes by id |
| `figma_get_images` | Render nodes to image URLs |
| `figma_get_image_fills` | Get image fill URLs in a file |
| `figma_get_comments` / `figma_post_comment` / `figma_delete_comment` | Read / add / delete comments |
| `figma_get_file_versions` | List file version history |
| `figma_get_team_projects` / `figma_get_project_files` | Browse team projects and their files |
| `figma_get_team_components` / `figma_get_team_styles` / `figma_get_component` | Components & styles |

### Jira

| Tool | Description |
|------|-------------|
| `jira_myself` | Verify creds and show the current user |
| `jira_search` | JQL search |
| `jira_get_issue` / `jira_create_issue` / `jira_update_issue` / `jira_delete_issue` | Issue CRUD |
| `jira_assign_issue` / `jira_add_watcher` | Assign / watch |
| `jira_add_comment` / `jira_list_comments` | Comments (plain text → ADF) |
| `jira_list_transitions` / `jira_transition_issue` | Workflow transitions |
| `jira_list_projects` / `jira_get_project` / `jira_list_issue_types` | Projects & types |
| `jira_list_boards` / `jira_list_sprints` / `jira_get_sprint_issues` | Agile boards & sprints |

### Confluence

| Tool | Description |
|------|-------------|
| `confluence_current_user` | Verify creds |
| `confluence_search` | CQL search |
| `confluence_get_page` / `confluence_get_page_by_title` | Read a page |
| `confluence_create_page` / `confluence_update_page` / `confluence_delete_page` | Page CRUD (auto version bump) |
| `confluence_get_page_children` | Child pages |
| `confluence_list_spaces` / `confluence_get_space` | Spaces |
| `confluence_add_comment` / `confluence_get_comments` | Comments |
| `confluence_get_attachments` | Attachments |

### Microsoft Teams

| Tool | Description |
|------|-------------|
| `teams_me` / `teams_list_users` | Identity & directory |
| `teams_list_joined_teams` / `teams_list_channels` / `teams_get_channel` | Teams & channels |
| `teams_list_channel_messages` / `teams_get_channel_message_replies` | Read channel chat |
| `teams_send_channel_message` / `teams_reply_to_channel_message` | Post to channels |
| `teams_list_chats` / `teams_get_chat_messages` / `teams_send_chat_message` | 1:1 / group chat |
| `teams_list_online_meetings` / `teams_get_online_meeting` | Meetings |
| `teams_list_meeting_recordings` / `teams_list_meeting_transcripts` | Recordings & transcripts (Graph beta) |

### Datadog

| Tool | Description |
|------|-------------|
| `datadog_validate` | Verify the API key |
| `datadog_query_metrics` / `datadog_list_active_metrics` / `datadog_get_metric_metadata` | Metrics |
| `datadog_list_monitors` / `datadog_get_monitor` / `datadog_create_monitor` / `datadog_update_monitor` / `datadog_delete_monitor` | Monitor CRUD |
| `datadog_mute_monitor` / `datadog_unmute_monitor` | Mute / unmute |
| `datadog_search_events` / `datadog_search_logs` | Events & logs |
| `datadog_list_dashboards` / `datadog_get_dashboard` | Dashboards |
| `datadog_list_slos` / `datadog_get_slo` | SLOs |

### PagerDuty

| Tool | Description |
|------|-------------|
| `pagerduty_validate` / `pagerduty_whoami` | Verify token / current user |
| `pagerduty_list_incidents` / `pagerduty_get_incident` / `pagerduty_create_incident` / `pagerduty_update_incident` | Incident CRUD |
| `pagerduty_acknowledge_incident` / `pagerduty_resolve_incident` | Ack / resolve |
| `pagerduty_add_note` / `pagerduty_list_notes` | Incident notes |
| `pagerduty_list_services` / `pagerduty_get_service` | Services |
| `pagerduty_list_schedules` / `pagerduty_get_schedule` / `pagerduty_list_oncalls` | Schedules & on-call |
| `pagerduty_list_users` / `pagerduty_list_escalation_policies` | Users & escalation |

### Slack

| Tool | Description |
|------|-------------|
| `slack_auth_test` | Verify the bot token |
| `slack_list_channels` / `slack_get_channel_info` / `slack_create_channel` / `slack_set_channel_topic` | Channels |
| `slack_invite_to_channel` / `slack_open_conversation` | Membership / DMs |
| `slack_post_message` / `slack_update_message` / `slack_delete_message` | Send / edit / delete |
| `slack_get_channel_history` / `slack_get_thread_replies` | Read messages |
| `slack_add_reaction` | React |
| `slack_list_users` / `slack_get_user_info` / `slack_get_user_by_email` | Users |
| `slack_search_messages` | Search (needs a user token with `search:read`) |

### Presto / Trino

| Tool | Description |
|------|-------------|
| `presto_connectivity` | Verify the connection (`SELECT 1`) |
| `presto_execute_query` | Run arbitrary SQL (handles the statement-polling protocol) |
| `presto_list_catalogs` / `presto_list_schemas` / `presto_list_tables` | Browse the catalog |
| `presto_describe_table` / `presto_show_create_table` | Inspect a table |
| `presto_list_functions` | List available functions |

## Setup

1. Install dependencies (a virtualenv is recommended):

   ```bash
   python -m venv .venv && source .venv/bin/activate
   pip install -r requirements.txt
   ```

2. Create a GitHub Personal Access Token at
   https://github.com/settings/tokens — a fine-grained token, or a classic
   token with the `repo` scope.

3. Export it:

   ```bash
   export GITHUB_TOKEN=ghp_your_token_here
   ```

4. (Optional) Check the server boots:

   ```bash
   python server.py   # Ctrl-C to exit
   ```

## Environments (dev / preprod / prod)

Set `MCP_ENV` to `dev` (default), `preprod` or `prod` to choose which deployment
the URL-based connections talk to. For `JENKINS_URL`, `JIRA_URL`,
`CONFLUENCE_URL`, `REDASH_URL` and `PRESTO_HOST` you can provide per-environment
overrides named `<ENV>_<VAR>`; the plain `<VAR>` is the fallback for any env.

```bash
MCP_ENV=prod
DEV_JENKINS_URL=https://dev-jenkins.example.com
PROD_JENKINS_URL=https://jenkins.example.com
JENKINS_URL=https://jenkins.example.com   # used when no <ENV>_ override is set
```

So a tool resolving `JENKINS_URL` gets the dev URL under `MCP_ENV=dev` and the
prod URL under `MCP_ENV=prod`. An unrecognized `MCP_ENV` falls back to `dev`.

`JIRA_PROJECTS_FILTER` (comma-separated project keys) scopes `jira_search` to
those projects by default — unless the JQL already names a project, or you pass
`scope_to_default_projects=False`.

## Verifying credentials

`smoke_test.py` calls each integration's lightweight verify tool (`github_whoami`,
`jira_myself`, `slack_auth_test`, ...). Integrations whose env vars aren't set are
skipped, so it's safe to run with only some credentials configured. It reads a
`.env` file next to it if present.

```bash
python smoke_test.py            # test everything that's configured
python smoke_test.py slack jira # test only the named integrations
```

```
  ✓ github      OK       login=octocat
  ✗ slack       FAIL     Slack API error on auth.test: invalid_auth
  – datadog     skipped  set DATADOG_API_KEY, DATADOG_APP_KEY to test
```

Exit code is non-zero if any configured integration fails.

## Connecting to a client

### Claude Code

```bash
claude mcp add mcp-setup \
  --env GITHUB_TOKEN=ghp_your_token_here \
  -- python server.py
```

### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "mcp-setup": {
      "command": "python",
      "args": [
        "server.py"
      ],
      "env": {
        "GITHUB_TOKEN": "ghp_your_token_here"
      }
    }
  }
}
```

Use the absolute path to the `python` inside your virtualenv (`.venv/bin/python`)
if you installed the dependencies there. Restart the client after editing the config.

`server.py` loads a project-root `.env` on startup, so you can keep credentials
there instead of in the client config's `env` block (real env vars still win).

### Project-scoped config (.mcp.json)

For per-project auto-discovery, copy `.mcp.json.example` to `.mcp.json` in the
project root and adjust the `command` path. Clients that read `.mcp.json` (e.g.
Claude Code) will then launch the server automatically from this directory.

## Adding a new integration

1. Create `integrations/<name>.py` with the async tool functions and a
   `register(mcp)` that calls `mcp.add_tool(fn)` for each. Read credentials from
   environment variables (use `integrations.environment.require_url` for any base
   URL so it honors `MCP_ENV`).
2. Import the module in `server.py` and add `<name>.register(mcp)`.
3. Add the env vars to `.env.example` and the verify tool to `smoke_test.py`.