Jira Thing
Um exemplo de servidor MCP para interagir com o Jira, implantável no Cloudflare Workers.
Documentação
Servidor Model Context Protocol (MCP) com OAuth do GitHub
Este projeto fornece um modelo para um servidor Model Context Protocol (MCP) que usa o GitHub para autenticação OAuth 2.0. Ele foi construído para rodar no Cloudflare Workers, fornecendo uma base robusta e escalável para seus próprios serviços MCP remotos.
Os usuários podem se conectar ao seu servidor MCP implantado e serão solicitados a entrar com sua conta do GitHub para autorizar o acesso.
Recursos
- Integração OAuth do GitHub: Autentica usuários com segurança via GitHub, atuando como cliente OAuth para o GitHub e servidor OAuth para o cliente MCP.
- Carregamento Dinâmico de Ferramentas: Demonstra como expor ferramentas condicionalmente com base na identidade do usuário autenticado.
- Ferramentas de Exemplo: Inclui duas ferramentas de exemplo:
- Uma ferramenta pública
adddisponível para todos os usuários autenticados. - Uma ferramenta restrita
generateImagedisponível apenas para uma lista predefinida de usuários autorizados.
- Uma ferramenta pública
- Implantação Serverless: Construído no Cloudflare Workers para uma arquitetura serverless escalável e de baixa manutenção.
- Gerenciamento Seguro de Segredos: Usa segredos do Wrangler para gerenciar credenciais sensíveis, evitando valores codificados no código-fonte.
Começando
Pré-requisitos
- Node.js (v18 ou posterior)
- Uma conta Cloudflare
npmou um gerenciador de pacotes compatível
Instalação
-
Clone o repositório:
git clone https://github.com/PortNumber53/mcp-jira-thing.git cd mcp-jira-thing -
Instale as dependências:
npm install
Frontend React (frontend/)
Um aplicativo de página única React + Vite fica em frontend/. Ele fornece o fluxo de login do GitHub para usuários e pode ser desenvolvido com o servidor Vite padrão.
cd mcp-jira-thing
npm install # install Worker + shared dependencies (repo root)
cd frontend
npm install # install local dependencies before development
npm run dev # starts the Vite development server with HMR
npm run dev:worker # runs the merged Worker locally on :18112
Para builds reproduzíveis e implantação:
npm run build # runs tsc + vite build (Worker deploy is from repo root)
npm run deploy # uploads the merged Worker and SPA assets via wrangler deploy
O Cloudflare Worker é definido na raiz do repositório (src/index.ts). Ele serve o SPA de frontend/dist/client em / e expõe o servidor MCP em /sse (e /mcp). A implantação é realizada a partir da raiz do repositório com npm run deploy, que compila o SPA primeiro. Executar npm run dev:worker em frontend/ inicia o mesmo Worker mesclado localmente usando ../wrangler.jsonc.
Aplicativo Slack (integração de projeto Jira por canal)
Se você quiser que usuários do Slack interajam com o Jira no contexto de um canal do Slack (por exemplo, criar/pesquisar issues contra um projeto Jira padrão por canal), conecte um aplicativo Slack a este Worker e armazene um mapeamento:
- ID do canal do Slack → chave do projeto Jira (por exemplo,
C01234567→ENG)
Este repositório não inclui endpoints do Slack ainda, mas as etapas abaixo descrevem a configuração que você precisará quando adicioná-los.
1) Crie um aplicativo Slack
No Slack, crie um aplicativo do zero e habilite:
- Interatividade e Atalhos (opcional, mas recomendado)
- Comandos de Barra (recomendado)
- Assinaturas de Eventos (opcional; útil para menções
@yourapp) - OAuth e Permissões
2) Configurações de OAuth + escopos necessários
Adicione uma URL de redirecionamento para o Worker, por exemplo:
http://localhost:18112/slack/oauth/callback(local)https://<your-worker>.<your-subdomain>.workers.dev/slack/oauth/callback(produção)
Escopos de token de bot sugeridos (ajuste conforme suas necessidades):
commands: habilita comandos de barra como/jirachat:write: posta respostas/mensagenschannels:reade/ougroups:read: lê metadados do canal (público vs privado)app_mentions:read(se usar eventos para menções)users:read(se quiser exibir nomes de usuário / enriquecer mensagens)
3) Configure URLs de solicitação do Slack (endpoints do Worker que você adicionará)
Uma vez implementado, o Slack deve apontar para endpoints do Worker como:
- URL de solicitação de comando de barra:
.../slack/commands - URL de solicitação de interatividade:
.../slack/interactions - URL de solicitação de eventos (se habilitado):
.../slack/events
Todos esses endpoints devem:
- Verificar assinaturas do Slack usando
SLACK_SIGNING_SECRET - Responder dentro de 3 segundos (use
response_urlou acompanhamentos assíncronos para chamadas Jira lentas)
4) Armazene o mapeamento "canal → projeto Jira"
Abordagem recomendada neste repositório:
- Armazene o mapeamento no Cloudflare KV (simples) ou em um Durable Object (consistência forte)
- Chave por ID de canal, valor inclui pelo menos
{ projectKey, updatedAt, updatedBy }
Exemplo de chave de mapeamento:
slack:channel-project:C01234567→{"projectKey":"ENG","updatedAt":...}
5) UX sugerida do Slack (comandos)
Um padrão prático é um comando /jira que define ou usa o projeto padrão do canal:
- Definir padrão:
/jira project set ENG - Mostrar padrão:
/jira project get - Criar issue:
/jira create "Bug title" --type Task - Pesquisar:
/jira search status=Open assignee=me
Detalhe de implementação: o manipulador lê o ID do canal do payload do Slack, procura a chave do projeto para aquele canal e então chama o cliente/ferramentas Jira existentes em src/tools/jira/ para executar a ação solicitada.
6) Variáveis de ambiente que você precisará
Adicione estas como segredos/variáveis do Wrangler (nomes são sugestões; escolha uma convenção e siga-a):
SLACK_SIGNING_SECRET: necessário para verificar solicitações do SlackSLACK_CLIENT_ID/SLACK_CLIENT_SECRET: necessário para o fluxo de instalação OAuth do SlackSLACK_BOT_TOKEN: necessário para chamar APIs do Slack (ou armazenar tokens por workspace após OAuth)
Se você suportar múltiplos workspaces do Slack, armazene as informações de instalação do workspace/equipe chaveadas por team_id, não globalmente.
Backend Go (backend/)
O backend Go expõe endpoints REST que servem dados ao frontend (ou outros consumidores). A implementação inicial inclui:
GET /healthz— sonda de saúde simples para balanceadores de carga e verificações de fumaça do Jenkins.GET /api/users?limit=50— retorna uma lista paginada de usuários NextAuth do banco de dados.
Variáveis de ambiente
Crie uma cópia de backend/env.example e forneça os valores necessários:
| Variável | Obrigatória | Descrição |
|---|---|---|
BACKEND_ADDR | opcional | Endereço em que o servidor HTTP escuta. Padrão :18111. |
DATABASE_URL | ✅ | DSN Postgres usado pelo backend em tempo de execução. |
MCP_SESSION_API_TOKEN | opcional | Credencial interna Node MCP → backend; padrão COOKIE_SECRET. |
BACKEND_HTTP_TIMEOUT_SECONDS | opcional | Timeout de solicitação de saída, padrão 15 segundos. |
go test e o código em tempo de execução esperam que as variáveis de ambiente estejam presentes. Ao executar localmente, você pode exportá-las ou usar um carregador dotenv (direnv, dotenvx, etc.).
Desenvolvimento local
cd backend
cp env.example .env # edit with your credentials (or export env vars)
go test ./...
go run ./cmd/server
# or via make
make test
make run
Recarga automática com Air
Air oferece recarga ao vivo para aplicações Go, para que as alterações sejam recompiladas e reiniciadas automaticamente durante o desenvolvimento, reduzindo os ciclos de feedback 1.
# install once (requires Go 1.25+)
go install github.com/air-verse/air@latest
# start the watcher from the backend directory
cd backend
make dev # runs `air -c .air.toml`
O Air usa a configuração em backend/.air.toml para recompilar ./tmp/main sempre que arquivos Go ou de ambiente mudarem, e então reinicia o servidor de forma transparente. Garanta que seus valores .env estejam presentes antes de iniciar o observador.
Fluxo de implantação
- Build/Teste:
make buildcompila um binário estático Linux embackend/bin/mcp-backend.make testexecuta os testes unitários. Ambos os comandos são orquestrados pelo pipeline Jenkins (veja abaixo). - Artefato: Jenkins compacta o binário em
backend/bin/mcp-backend.tar.gze o publica como artefato de build. - Script de implantação:
scripts/deploy-backend.shcompila cruzadamente o binário Linux, envia viascp, descompacta em$DEPLOY_PATHe opcionalmente reinicia um serviço systemd quandoSERVICE_NAMEé fornecido.
Pipeline Jenkins
Este repositório agora contém um Jenkinsfile de nível superior que executa as seguintes etapas:
- Checkout — puxa o repositório para o build atual.
- Teste Go — executa
go test ./...dentro debackend/. - Build do Backend — executa
make buildpara gerar o bináriomcp-backend. - Arquivar Artefato — compacta o binário e o arquiva para recuperação posterior.
- Implantar (somente master) — executa
scripts/deploy-backend.sh, que espera as seguintes variáveis de ambiente fornecidas pelas credenciais do Jenkins ou configuração do job:DEPLOY_HOST: Host/IP do servidor de produção (Arch Linux).DEPLOY_USER: Usuário SSH com permissão para escrever emDEPLOY_PATHe executarsudo systemctl restartno serviço de destino.DEPLOY_PATH: Diretório de destino no servidor (por exemplo,/opt/mcp-backend).SERVICE_NAME(opcional): nome da unidade systemd para reiniciar após a implantação.
A etapa de implantação só é executada para builds no branch master, então branches de recursos permanecem apenas para teste. O Jenkins deve fornecer acesso SSH, tipicamente via uma credencial de chave SSH associada à conta DEPLOY_USER. Revise scripts/deploy-backend.sh para detalhes adicionais ou pontos de personalização.
Configuração e Implantação
Siga estas etapas para configurar e implantar seu servidor MCP.
1. Crie um aplicativo OAuth do GitHub
Primeiro, você precisa criar um aplicativo OAuth do GitHub para obter suas credenciais de cliente.
- URL da página inicial:
https://<your-worker-name>.<your-subdomain>.workers.dev - URL de callback de autorização:
https://<your-worker-name>.<your-subdomain>.workers.dev/callback/github
Depois que o aplicativo for criado, anote o ID do cliente e gere um novo segredo do cliente.
2. Configure os segredos
Em seguida, use o Wrangler para armazenar com segurança suas credenciais do GitHub e uma chave de criptografia de sessão como segredos.
# Will prompt for your GitHub Client ID
npx wrangler secret put GITHUB_CLIENT_ID
# Will prompt for your GitHub Client Secret
npx wrangler secret put GITHUB_CLIENT_SECRET
# Will prompt for a random string used to sign session cookies
npx wrangler secret put SESSION_SECRET
# Optionally, provide COOKIE_SECRET if you need an override for local testing
npx wrangler secret put COOKIE_SECRET
Para o SESSION_SECRET, você pode gerar uma string aleatória segura com openssl rand -hex 32.
3. Armazenamento de sessão
O estado OAuth e os dados de sessão do usuário são armazenados em cookies assinados e somente HTTP; nenhum namespace Cloudflare KV é necessário. Garanta que SESSION_SECRET (ou COOKIE_SECRET) esteja configurado para que o Worker possa assinar e validar esses cookies com segurança. Se você usou COOKIE_ENCRYPTION_KEY anteriormente, renomeie esse segredo para SESSION_SECRET.
4. Autorize usuários
Para conceder acesso a ferramentas restritas como generateImage, você deve adicionar os nomes de usuário do GitHub dos usuários autorizados ao conjunto ALLOWED_USERNAMES em src/index.ts.
// src/index.ts
const ALLOWED_USERNAMES = new Set<string>([
"PortNumber53",
// Add other authorized GitHub usernames here
]);
5. Implante o Worker
Finalmente, implante seu worker configurado no Cloudflare.
npx wrangler deploy
Ferramentas Disponíveis
Este servidor MCP expõe as seguintes ferramentas:
-
add- Descrição: Adiciona dois números.
- Acesso: Público (disponível para todos os usuários autenticados).
- Parâmetros:
a(número),b(número).
-
generateImage- Descrição: Gera uma imagem usando o modelo
@cf/black-forest-labs/flux-1-schnell. - Acesso: Restrito (disponível apenas para usuários em
ALLOWED_USERNAMES). - Parâmetros:
prompt(string),steps(número, 4-8).
- Descrição: Gera uma imagem usando o modelo
Uso
Você pode testar seu servidor remoto usando o MCP Inspector:
npx @modelcontextprotocol/inspector@latest
Digite a URL SSE do seu worker (https://<your-worker-name>.<your-subdomain>.workers.dev/sse) e clique em Conectar. Você será redirecionado ao GitHub para autenticar. Após a autenticação, você verá as ferramentas disponíveis no Inspector.
Estrutura do Projeto
src/index.ts: O ponto de entrada principal para o Cloudflare Worker. Define o servidor MCP, suas ferramentas e a lógica para acesso condicional a ferramentas.src/github-handler.ts: Contém a lógica para lidar com o fluxo OAuth do GitHub.src/workers-oauth-utils.ts: Fornece funções utilitárias para o processo OAuth, adaptadas da bibliotecaworkers-oauth-provider.wrangler.jsonc: O arquivo de configuração para o Cloudflare Worker.package.json: Define scripts do projeto e dependências.
Agora você tem um servidor MCP remoto implantado!
Controle de Acesso
Este servidor MCP usa OAuth do GitHub para autenticação. Todos os usuários autenticados do GitHub podem acessar ferramentas básicas como "add" e "userInfoOctokit".
A ferramenta "generateImage" é restrita a usuários específicos do GitHub listados na configuração ALLOWED_USERNAMES:
// Add GitHub usernames for image generation access
const ALLOWED_USERNAMES = new Set(["yourusername", "teammate1"]);
Acesse o servidor MCP remoto pelo Claude Desktop
Abra o Claude Desktop e navegue até Settings -> Developer -> Edit Config. Isso abre o arquivo de configuração que controla quais servidores MCP o Claude pode acessar.
Substitua o conteúdo pela configuração a seguir. Depois de reiniciar o Claude Desktop, uma janela do navegador será aberta mostrando sua página de login OAuth. Conclua o fluxo de autenticação para conceder ao Claude acesso ao seu servidor MCP. Após conceder o acesso, as ferramentas ficarão disponíveis para uso.
{
"mcpServers": {
"math": {
"command": "npx",
"args": [
"mcp-remote",
"https://mcp-github-oauth.<your-subdomain>.workers.dev/sse"
]
}
}
}
Assim que as Tools (em 🔨) aparecerem na interface, você pode pedir ao Claude para usá-las. Por exemplo: "Você poderia usar a ferramenta de matemática para somar 23 e 19?". O Claude deve acionar a ferramenta e mostrar o resultado gerado pelo servidor MCP.
Para desenvolvimento local
Se você quiser iterar e testar seu servidor MCP, pode fazer isso no desenvolvimento local. Isso exigirá que você crie outro OAuth App no GitHub:
- Para a Homepage URL, especifique
http://localhost:18112 - Para a Authorization callback URL, especifique
http://localhost:18112/callback/github - Anote seu Client ID e gere um Client secret.
- Crie um arquivo
.dev.varsna raiz do seu projeto com:
GITHUB_CLIENT_ID=your_development_github_client_id
GITHUB_CLIENT_SECRET=your_development_github_client_secret
Desenvolver e testar
Execute o servidor localmente para disponibilizá-lo em http://localhost:18112
wrangler dev
Para testar o servidor local, insira http://localhost:18112/sse no Inspector e clique em conectar. Depois de seguir as instruções, você poderá "List Tools".
Usando Claude e outros clientes MCP
Ao usar o Claude para se conectar ao seu servidor MCP remoto, você pode ver algumas mensagens de erro. Isso acontece porque o Claude Desktop ainda não suporta servidores MCP remotos, então às vezes ele fica confuso. Para verificar se o servidor MCP está conectado, passe o mouse sobre o ícone 🔨 no canto inferior direito da interface do Claude. Você deve ver suas ferramentas disponíveis lá.
Usando Cursor e outros clientes MCP
Para conectar o Cursor ao seu servidor MCP, escolha Type: "Command" e no campo Command, combine os campos command e args em um só (ex.: npx mcp-remote https://<your-worker-name>.<your-subdomain>.workers.dev/sse).
Observe que, embora o Cursor suporte servidores HTTP+SSE, ele não suporta autenticação, então você ainda precisa usar mcp-remote (e usar um servidor STDIO, não um HTTP).
Você pode conectar seu servidor MCP a outros clientes MCP, como o Windsurf, abrindo o arquivo de configuração do cliente, adicionando o mesmo JSON usado na configuração do Claude e reiniciando o cliente MCP.
Como funciona?
Transporte e persistência do MCP
Os Workers do Cloudflare roteiam o tráfego /sse e /mcp para o servidor MCP Node.js autônomo configurado por MCP_SERVER_URL. O serviço Node não se conecta diretamente ao banco de dados. Ele persiste a identidade da sessão de transporte, metadados de inicialização, propriedade do locatário, expiração e carimbos de última visualização por meio da API interna protegida do backend Go. O backend Go é o único proprietário do banco de dados e armazena esses registros no PostgreSQL.
Sessões HTTP transmissíveis podem ser reconstruídas a partir do PostgreSQL após uma reinicialização do processo Node. Fluxos de resposta ao vivo e sockets SSE legados permanecem necessariamente locais ao processo; se um socket SSE for interrompido, o cliente se reconecta e cria uma nova sessão persistida.
Defina MCP_SESSION_API_TOKEN com o mesmo valor no backend Go e no serviço MCP Node. Se omitido, ambos os serviços podem usar o COOKIE_SECRET/SESSION_SECRET compartilhado existente. MCP_SESSION_TTL_SECONDS controla o tempo de vida da sessão contínua do serviço Node e o padrão é 24 horas.
MCP Remote
A biblioteca MCP Remote permite que seu servidor exponha ferramentas que podem ser invocadas por clientes MCP, como o Inspector. Ela:
- Define o protocolo de comunicação entre clientes e seu servidor
- Fornece uma maneira estruturada de definir ferramentas
- Lida com a serialização e desserialização de solicitações e respostas
- Mantém a conexão Server-Sent Events (SSE) entre clientes e seu servidor
Footnotes
-
Air é um utilitário de recarga ao vivo de código aberto para aplicações Go que observa o código-fonte, recompila e reexecuta o binário compilado automaticamente para agilizar o desenvolvimento air-verse/air. ↩