| name | GitHub Agentic Workflows MCP Configuration |
| description | Comprehensive guide for MCP (Model Context Protocol) server setup, transport protocols, configuration validation, lifecycle management, tool discovery, and error handling patterns |
| license | Apache-2.0 |
| version | 2.0.1 |
| last_updated | "2026-04-13T00:00:00.000Z" |
| tags | ["github-agentic-workflows","mcp","model-context-protocol","server-configuration","transport-protocols","tool-discovery","lifecycle-management","error-handling","stdio","http","sse"] |
🔌 GitHub Agentic Workflows MCP Configuration
🔴 AI FIRST Quality Principle
Apply the AI FIRST principle: never accept first-pass quality. Minimum 2 iterations. Read all output, improve every section. No shortcuts.
📋 Overview
This skill provides comprehensive guidance for configuring Model Context Protocol (MCP) servers in GitHub Agentic Workflows. MCP enables AI agents to interact with external tools and data sources through a standardized protocol. Understanding MCP configuration is essential for building powerful, extensible agentic workflows.
What is Model Context Protocol (MCP)?
Model Context Protocol (MCP) is a standardized protocol for connecting AI models to external tools, data sources, and services:
- Standardized Interface: Consistent API for tool registration, discovery, and invocation
- Multiple Transports: Support for stdio, HTTP, and Server-Sent Events (SSE)
- Tool Discovery: Dynamic tool registration and capability discovery
- Type Safety: JSON Schema validation for tool inputs and outputs
- Lifecycle Management: Server startup, health checks, graceful shutdown
- Error Handling: Structured error responses and retry mechanisms
Why Use MCP Servers?
MCP servers provide several benefits for agentic workflows:
- ✅ Extensibility: Add new tools without modifying agent code
- ✅ Reusability: Share MCP servers across multiple agents and projects
- ✅ Isolation: Run tools in separate processes for security and stability
- ✅ Standardization: Use community-maintained MCP servers
- ✅ Polyglot: Write servers in any language (Node.js, Python, Go, Rust)
- ✅ Discoverability: Agents automatically discover available tools
🏗️ MCP Architecture
System Overview
┌─────────────────────────────────────────────────────────────┐
│ GitHub Copilot Agent │
│ (AI Model + Orchestration) │
└──────────────────────┬──────────────────────────────────────┘
│ Tool Calls
│ (JSON-RPC 2.0)
▼
┌─────────────────────────────────────────────────────────────┐
│ MCP Client Runtime │
│ (Tool Discovery & Invocation) │
└─┬──────────────────┬──────────────────┬────────────────────┘
│ stdio │ HTTP │ SSE
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Filesystem │ │ GitHub API │ │ Database │
│ MCP Server │ │ MCP Server │ │ MCP Server │
└──────────────┘ └──────────────┘ └──────────────┘
Configuration File Structure
MCP servers are configured in .github/copilot-mcp.json:
{
"$schema": "https://github.com/modelcontextprotocol/schema/v1",
"mcpServers": {
"server-name": {
"type": "local",
"command": "command-to-run",
"args": ["arg1", "arg2"],
"env": {
"ENV_VAR": "value"
},
"tools": ["*"]
}
}
}
🚀 MCP Server Setup Patterns
Pattern 1: Local stdio Server
Use case: File system operations, git commands, local tools.
{
"mcpServers": {
"filesystem": {
"type": "local",
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/home/runner/work/myrepo/myrepo"
],
"env": {},
"tools": ["*"]
}
}
}
Implementation (Node.js):
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import fs from 'fs/promises';
import path from 'path';
class FileSystemMCPServer {
constructor(rootPath) {
this.rootPath = path.resolve(rootPath);
this.server = new Server({
name: 'filesystem',
version: '1.0.0',
}, {
capabilities: {
tools: {},
},
});
this.setupTools();
}
setupTools() {
this.server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'read_file',
description: 'Read contents of a file',
inputSchema: {
type: ,
: {
: {
: ,
: ,
},
},
: [],
},
},
{
: ,
: ,
: {
: ,
: {
: { : },
: { : },
},
: [, ],
},
},
{
: ,
: ,
: {
: ,
: {
: { : },
},
: [],
},
},
],
}));
..(, (request) => {
{ name, : args } = request.;
(name) {
:
.(args.);
:
.(args., args.);
:
.(args.);
:
();
}
});
}
() {
resolved = path.(., filePath);
(!resolved.(.)) {
();
}
resolved;
}
() {
validated = .(filePath);
content = fs.(validated, );
{
: [
{
: ,
: content,
},
],
};
}
() {
validated = .(filePath);
fs.(validated, content, );
{
: [
{
: ,
: ,
},
],
};
}
() {
validated = .(dirPath);
entries = fs.(validated, { : });
files = entries.( ({
: entry.,
: entry.() ? : ,
}));
{
: [
{
: ,
: .(files, , ),
},
],
};
}
() {
transport = ();
..(transport);
.();
}
}
rootPath = process.[] || process.();
server = (rootPath);
server.().(.);
Usage:
npx -y @modelcontextprotocol/server-filesystem /workspace
{"jsonrpc":"2.0","id":1,"method":"tools/list"}
{"jsonrpc":"2.0","id":1,"result":{"tools":[...]}}
Pattern 2: HTTP Server
Use case: Remote services, APIs, databases.
{
"mcpServers": {
"github-api": {
"type": "http",
"url": "https://mcp.github.com/v1",
"headers": {
"Authorization": "Bearer ${{ secrets.GITHUB_TOKEN }}"
},
"tools": ["*"]
}
}
}
Implementation (Node.js with Express):
import express from 'express';
import { Octokit } from '@octokit/rest';
const app = express();
app.use(express.json());
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN,
});
app.post('/mcp/tools/list', async (req, res) => {
res.json({
tools: [
{
name: 'github_create_issue',
description: 'Create a GitHub issue',
inputSchema: {
type: 'object',
properties: {
owner: { type: 'string' },
repo: { type: 'string' },
title: { type: 'string' },
body: { type: 'string' },
},
required: ['owner', 'repo', 'title'],
},
},
{
name: 'github_list_issues',
: ,
: {
: ,
: {
: { : },
: { : },
: { : , : [, , ] },
},
: [, ],
},
},
],
});
});
app.(, (req, res) => {
{ name, : args } = req.;
{
(name) {
: {
{ data } = octokit..({
: args.,
: args.,
: args.,
: args.,
});
res.({
: [
{
: ,
: ,
},
],
});
;
}
: {
{ data } = octokit..({
: args.,
: args.,
: args. || ,
});
res.({
: [
{
: ,
: .(data, , ),
},
],
});
;
}
:
res.().({ : });
}
} (error) {
res.().({ : error. });
}
});
app.(, {
res.({ : });
});
= process.. || ;
app.(, {
.();
});
Pattern 3: Server-Sent Events (SSE)
Use case: Real-time updates, streaming data, webhooks.
{
"mcpServers": {
"realtime-monitor": {
"type": "sse",
"url": "https://monitor.example.com/events",
"headers": {
"Authorization": "Bearer ${{ secrets.API_TOKEN }}"
},
"tools": ["*"]
}
}
}
Implementation (Node.js with SSE):
import express from 'express';
const app = express();
const clients = new Set();
app.get('/events', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
clients.add(res);
res.write(`event: connected\ndata: {"status":"connected"}\n\n`);
req.on('close', () => {
clients.delete(res);
});
});
function broadcastEvent(eventType, data) {
const message = `event: ${eventType}\ndata: ${JSON.stringify(data)}\n\n`;
for (const client of clients) {
client.write(message);
}
}
app.(, express.(), {
{ name, : args } = req.;
(name === ) {
subscription = {
: args.,
: args.,
};
(, {
: ,
: ,
});
res.({
: [
{
: ,
: ,
},
],
});
} {
res.().({ : });
}
});
( {
(, {
: ,
: ,
: ().(),
});
}, );
= process.. || ;
app.(, {
.();
});
🔌 Transport Protocols
stdio Transport
Characteristics:
- Process-to-process communication via stdin/stdout
- Lowest latency
- Best for local tools
- Automatic lifecycle management
Advantages:
- ✅ Simple to implement
- ✅ No network overhead
- ✅ Automatic process cleanup
- ✅ Secure (no network exposure)
Disadvantages:
- ❌ Single client per server instance
- ❌ No remote access
- ❌ Requires process spawning
Configuration:
{
"mcpServers": {
"local-tool": {
"type": "local",
"command": "node",
"args": ["server.js"],
"env": {
"NODE_ENV": "production"
},
"tools": ["*"]
}
}
}
HTTP Transport
Characteristics:
- RESTful JSON-RPC over HTTP/HTTPS
- Stateless request/response
- Can be load balanced
- Supports authentication
Advantages:
- ✅ Remote server support
- ✅ Multiple concurrent clients
- ✅ Standard HTTP infrastructure
- ✅ Load balancing and scaling
Disadvantages:
- ❌ Higher latency
- ❌ Requires authentication
- ❌ Network security considerations
Configuration:
{
"mcpServers": {
"remote-api": {
"type": "http",
"url": "https://api.example.com/mcp/v1",
"headers": {
"Authorization": "Bearer ${MCP_API_TOKEN}",
"X-API-Version": "1.0"
},
"timeout": 30000,
"retries": 3,
"tools": ["*"]
}
}
}
Server-Sent Events (SSE) Transport
Characteristics:
- One-way server-to-client streaming
- Real-time event notifications
- Automatic reconnection
- HTTP-based
Advantages:
- ✅ Real-time updates
- ✅ Efficient for event streams
- ✅ Automatic reconnection
- ✅ Works through firewalls
Disadvantages:
- ❌ One-way only (server → client)
- ❌ Requires persistent connection
- ❌ Browser compatibility (not relevant for agents)
Configuration:
{
"mcpServers": {
"event-stream": {
"type": "sse",
"url": "https://events.example.com/stream",
"headers": {
"Authorization": "Bearer ${EVENT_TOKEN}"
},
"reconnect": true,
"reconnectDelay": 5000,
"tools": ["*"]
}
}
}
✅ Configuration Validation
Schema Validation
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv({ allErrors: true });
addFormats(ajv);
const mcpConfigSchema = {
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'object',
properties: {
mcpServers: {
type: 'object',
patternProperties: {
'^[a-zA-Z0-9_-]+$': {
oneOf: [
{
type: 'object',
properties: {
type: { const: 'local' },
command: { type: 'string', minLength: 1 },
args: { type: 'array', items: { type: 'string' } },
env: {
type: 'object',
patternProperties: {
'^[A-Z_][A-Z0-9_]*$': { type: 'string' },
},
},
: {
: [
{ : , : { : } },
{ : , : { : }, : },
],
},
},
: [, ],
: ,
},
{
: ,
: {
: { : },
: { : , : },
: {
: ,
: {
: { : },
},
},
: { : , : },
: { : , : },
: {
: [
{ : , : { : } },
{ : , : { : }, : },
],
},
},
: [, ],
: ,
},
{
: ,
: {
: { : },
: { : , : },
: {
: ,
: {
: { : },
},
},
: { : },
: { : , : },
: {
: [
{ : , : { : } },
{ : , : { : }, : },
],
},
},
: [, ],
: ,
},
],
},
},
},
},
: [],
: ,
};
validate = ajv.(mcpConfigSchema);
() {
valid = (config);
(!valid) {
errors = validate..( ({
: err.,
: err.,
: err.,
}));
(
);
}
;
}
fs ;
config = .(
fs.(, )
);
{
(config);
.();
} (error) {
.(, error.);
process.();
}
Runtime Validation
class MCPConfigValidator {
constructor(config) {
this.config = config;
}
async validateAll() {
const errors = [];
for (const [name, server] of Object.entries(this.config.mcpServers)) {
try {
await this.validateServer(name, server);
} catch (error) {
errors.push({
server: name,
error: error.message,
});
}
}
if (errors.length > 0) {
throw new Error(
`MCP server validation failed:\n${JSON.stringify(errors, null, 2)}`
);
}
return true;
}
async validateServer(name, server) {
switch (server.type) {
case 'local':
await this.(name, server);
;
:
.(name, server);
;
:
.(name, server);
;
:
();
}
}
() {
{ execSync } = ();
{
(, { : });
} (error) {
();
}
(server.) {
( [key, value] .(server.)) {
(value.() && value.()) {
envVar = value.()[];
(!process.[envVar]) {
();
}
}
}
}
}
() {
{
response = (, {
: server. || {},
: .(),
});
(!response.) {
();
}
} (error) {
();
}
}
() {
( {
eventSource = (server., {
: server. || {},
});
timeout = ( {
eventSource.();
( ());
}, );
eventSource.(, {
(timeout);
eventSource.();
();
});
eventSource. = {
(timeout);
eventSource.();
( ());
};
});
}
}
validator = (config);
validator.();
🔄 Server Lifecycle Management
Startup Sequence
class MCPLifecycleManager {
constructor(config) {
this.config = config;
this.servers = new Map();
this.health = new Map();
}
async startAll() {
console.log('🚀 Starting MCP servers...');
const promises = Object.entries(this.config.mcpServers).map(
async ([name, server]) => {
try {
await this.startServer(name, server);
console.log(`✅ Started: ${name}`);
} catch (error) {
console.error(`❌ Failed to start ${name}:`, error.message);
throw error;
}
}
);
await Promise.all(promises);
console.log();
}
() {
(config.) {
:
.(name, config);
:
.(name, config);
:
.(name, config);
:
();
}
}
() {
{ spawn } = ();
process = (config., config. || [], {
: [, , ],
: { ...process., ...config. },
});
.(process);
..(name, { : , process });
..(name, );
.(name, process);
}
() {
( {
timer = ( {
( ());
}, timeout);
process..(, {
message = data.();
(message.() || message.()) {
(timer);
();
}
});
process.(, {
(timer);
(error);
});
process.(, {
(timer);
( ());
});
});
}
() {
process.(, {
.();
..(name, );
(code !== ) {
.();
( {
.(name);
}, );
}
});
process.(, {
.(, error.);
..(name, );
});
( () => {
healthy = .(name);
..(name, healthy ? : );
}, );
}
() {
server = ..(name);
(!server) ;
(server.) {
:
!server..;
:
{
response = (, {
: .(),
});
response.;
} (error) {
;
}
:
server.;
:
;
}
}
() {
config = ..[name];
.(name);
.(name, config);
}
() {
server = ..(name);
(!server) ;
(server.) {
:
server..();
( {
timeout = ( {
server..();
();
}, );
server..(, {
(timeout);
();
});
});
;
:
:
(server.) {
server..();
}
;
}
..(name);
..(name);
}
() {
.();
promises = .(..()).(
(name) => {
{
.(name);
.();
} (error) {
.(, error.);
}
}
);
.(promises);
.();
}
() {
status = {};
( [name, health] .) {
status[name] = health;
}
status;
}
}
manager = (config);
manager.();
.(, manager.());
process.(, () => {
manager.();
process.();
});
🔍 Tool Discovery and Registration
Dynamic Tool Discovery
class MCPToolDiscovery {
constructor(servers) {
this.servers = servers;
this.tools = new Map();
}
async discoverAll() {
console.log('🔍 Discovering MCP tools...');
for (const [serverName, server] of this.servers) {
try {
const tools = await this.discoverTools(serverName, server);
for (const tool of tools) {
this.registerTool(serverName, tool);
}
console.log(`✅ Discovered ${tools.length} tools from ${serverName}`);
} catch (error) {
console.error(`❌ Failed to discover tools from ${serverName}:`, error.message);
}
}
console.log(`✅ Total tools discovered: ${this.tools.size}`);
}
() {
(server.) {
:
.(server);
:
.(server);
:
.(server);
:
();
}
}
() {
( {
request = {
: ,
: ,
: ,
: {},
};
server...(.(request) + );
server...(, {
response = .(data.());
(response.) {
( (response..));
} {
(response..);
}
});
( {
( ());
}, );
});
}
() {
response = (, {
: ,
: {
: ,
...server.,
},
: .({
: ,
: ,
: ,
}),
});
result = response.();
result..;
}
() {
fullName = ;
..(fullName, {
: serverName,
: tool.,
: tool.,
: tool.,
});
}
() {
..(fullName);
}
() {
toolList = .(..());
(filter) {
toolList.(
tool..(filter) ||
tool..(filter)
);
}
toolList;
}
() {
tool = .(fullName);
(!tool) {
();
}
.(tool., args);
server = ..(tool.);
.(server, tool., args);
}
() {
= ();
ajv = ();
validate = ajv.(schema);
(!(input)) {
(
);
}
}
() {
request = {
: ,
: .(),
: ,
: {
: toolName,
: args,
},
};
(server.) {
: {
( {
server...(.(request) + );
server...(, {
response = .(data.());
(response.) {
( (response..));
} {
(response.);
}
});
( {
( ());
}, );
});
}
: {
response = (, {
: ,
: {
: ,
...server.,
},
: .(request),
});
result = response.();
(result.) {
(result..);
}
result.;
}
:
();
}
}
}
discovery = (manager.);
discovery.();
.(, discovery.());
result = discovery.(, {
: ,
});
.(, result);
⚠️ Error Handling Patterns
Retry with Exponential Backoff
class RetryHandler {
constructor(maxRetries = 3, baseDelay = 1000) {
this.maxRetries = maxRetries;
this.baseDelay = baseDelay;
}
async execute(fn, context = {}) {
let lastError;
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (this.isNonRetryable(error)) {
throw error;
}
if (attempt < this.maxRetries) {
const delay = this.calculateDelay(attempt);
console.warn(
`Attempt ${attempt + 1} failed: ${error.message}. Retrying in ${delay}ms...`
);
await this.sleep(delay);
}
}
}
throw (
);
}
() {
(
error..() ||
error..() ||
error..() ||
error..()
);
}
() {
exponentialDelay = . * .(, attempt);
jitter = .() * .;
.(exponentialDelay + jitter, );
}
() {
( (resolve, ms));
}
}
retry = ();
result = retry.( () => {
discovery.(, {
: ,
: ,
: ,
});
});
Circuit Breaker
class CircuitBreaker {
constructor(threshold = 5, timeout = 60000, resetTimeout = 300000) {
this.threshold = threshold;
this.timeout = timeout;
this.resetTimeout = resetTimeout;
this.failures = 0;
this.lastFailureTime = null;
this.state = 'CLOSED';
}
async execute(fn) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailureTime > this.resetTimeout) {
this.state = 'HALF_OPEN';
console.log('Circuit breaker entering HALF_OPEN state');
} else {
throw new Error('Circuit breaker is OPEN');
}
}
{
result = .(fn);
.();
result;
} (error) {
.();
error;
}
}
() {
.([
(),
(
( ( ()), .)
),
]);
}
() {
. = ;
(. === ) {
.();
. = ;
}
}
() {
.++;
. = .();
(. >= .) {
.();
. = ;
}
}
() {
{
: .,
: .,
: .,
};
}
}
breaker = ();
{
result = breaker.( () => {
();
});
} (error) {
.(, error.);
.(, breaker.());
}
Graceful Degradation
class GracefulDegradation {
constructor(primaryFn, fallbackFn) {
this.primaryFn = primaryFn;
this.fallbackFn = fallbackFn;
this.primaryFailures = 0;
this.useFallback = false;
}
async execute(...args) {
if (this.useFallback) {
return this.executeFallback(...args);
}
try {
const result = await this.primaryFn(...args);
this.primaryFailures = 0;
return result;
} catch (error) {
this.primaryFailures++;
console.warn(
`Primary function failed (${this.primaryFailures} times): ${error.message}`
);
if (this.primaryFailures >= 3) {
console.warn();
. = ;
}
.(...args);
}
}
() {
{
.(...args);
} (error) {
(
);
}
}
() {
. = ;
. = ;
}
}
toolInvoker = (
(toolName, args) => {
discovery.(toolName, args);
},
(toolName, args) => {
.();
(toolName, args);
}
);
result = toolInvoker.(, {
: ,
: ,
: ,
});
🔐 Security Considerations
Authentication
{
"mcpServers": {
"secure-api": {
"type": "http",
"url": "https://api.example.com/mcp/v1",
"headers": {
"Authorization": "Bearer ${MCP_API_TOKEN}",
"X-API-Key": "${API_KEY}"
},
"tools": ["*"]
}
}
}
TLS/SSL
import https from 'https';
import fs from 'fs';
const tlsOptions = {
ca: fs.readFileSync('ca-cert.pem'),
cert: fs.readFileSync('client-cert.pem'),
key: fs.readFileSync('client-key.pem'),
rejectUnauthorized: true,
minVersion: 'TLSv1.3',
};
const agent = new https.Agent(tlsOptions);
const response = await fetch('https://secure-mcp.example.com', {
agent,
});
Input Validation
function validateToolInput(schema, input) {
const Ajv = require('ajv');
const ajv = new Ajv({ allErrors: true });
const validate = ajv.compile(schema);
if (!validate(input)) {
const errors = validate.errors.map(err => ({
path: err.instancePath,
message: err.message,
}));
throw new Error(
`Invalid tool input:\n${JSON.stringify(errors, null, 2)}`
);
}
}
🎓 Related Skills
- gh-aw-security-architecture: Security for MCP servers
- gh-aw-tools-ecosystem: Available MCP tools
- gh-aw-safe-outputs: Output sanitization
- github-actions-workflows: CI/CD integration
🆕 MCP in Agentic Workflows (v0.68.1)
MCP servers extend agent capabilities through standardized tool interfaces. In gh-aw, the MCP Gateway runs inside the agent container, routing requests to Docker-hosted MCP servers.
Key patterns:
- stdio transport — Local MCP servers communicating via stdin/stdout
- HTTP transport — Remote MCP servers (e.g.,
https://api.githubcopilot.com/mcp/insiders)
- SSE transport — Server-sent events for streaming responses
Configure via a top-level mcp-servers key in workflow frontmatter (repo-level definitions go in .github/copilot-mcp.json):
---
mcp-servers:
github-mcp:
url: https://api.githubcopilot.com/mcp/insiders
custom:
command: npx
args: ["-y", "@my/mcp-server"]
tools:
github:
toolsets: [issues]
---
🔍 MCP Server Inspection (v0.68.1)
Use the gh aw mcp inspect command to analyze and debug MCP servers configured in agentic workflows:
Inspection Commands
gh aw mcp inspect
gh aw mcp inspect news-propositions
gh aw mcp inspect news-propositions --server riksdag-regering
gh aw mcp inspect news-propositions --server riksdag-regering --tool search_dokument
What --tool Flag Provides
The --tool flag provides detailed information about a specific tool, including:
- Tool name, title, and description
- Input schema and parameters (JSON Schema)
- Whether the tool is allowed in the workflow configuration
- Annotations and additional metadata
Note: The --tool flag requires the --server flag to specify which MCP server contains the tool.
riksdagsmonitor MCP Server Configuration
All agentic workflows in this repository configure 3 custom MCP servers:
mcp-servers:
riksdag-regering:
url: https://riksdag-regering-ai.onrender.com/mcp
allowed: ["*"]
scb:
container: "node:26-alpine"
entrypoint: "npx"
entrypointArgs: ["-y", "@jarib/pxweb-mcp@2.0.0", "--url", "https://api.scb.se/OV0104/v2beta"]
allowed: ["*"]
world-bank:
container: "node:26-alpine"
entrypoint: "npx"
entrypointArgs: ["-y", "worldbank-mcp@1.0.1"]
allowed: ["*"]
Copilot Agent MCP Configuration (.github/copilot-mcp.json)
For Copilot coding agent sessions (not agentic workflows), MCP servers are configured in .github/copilot-mcp.json:
{
"mcpServers": {
"riksdag-regering": { "type": "http", "url": "..." },
"scb": { "type": "local", "command": "npx", "args": [...] },
"world-bank": { "type": "local", "command": "npx", "args": [...] },
"github": { "type": "http", "url": "https://api.githubcopilot.com/mcp/insiders"
📚 References
✅ Remember
Last Updated: 2026-04-02
Version: 2.0.0
License: Apache-2.0
🔗 Integration with Riksdagsmonitor agentic workflows
This gh-aw skill is applied by the 11 agentic news workflows in .github/workflows/news-*.md. Their domain contract (analysis-artifact product, gate, article contract) lives in:
Upstream gh-aw docs (v0.69.3): abridged · complete · agentic-workflows blog series · source repo · GitHub CLI manual.
🌐 IMF Integration is Intentionally Non-MCP (CLI Pattern)
Effective: 2026-04-24
Why IMF is a CLI, not an MCP server
The IMF integration in Riksdagsmonitor is delivered as a TypeScript CLI (tsx scripts/imf-fetch.ts), not as an MCP server. This is a conscious architectural decision documented here to prevent future contributors from "fixing" the omission:
- No upstream MCP server exists for IMF data (as of 2026-04-24)
- Two endpoints to unify — IMF Datamapper REST and IMF SDMX 3.0; CLI wraps both behind one interface
- Vintage discipline requires deterministic logic — vintage labelling, supersedes-chain, SHA-256 pinning are easier to express in TypeScript than MCP tool descriptors
- Cache is filesystem-native —
analysis/imf/ + analysis/daily/*/economic-data.json are git-tracked artefacts; MCP servers would add an indirection layer
MCP servers in .github/copilot-mcp.json
| Server | Coverage |
|---|
riksdag-regering-mcp | Swedish parliamentary primary source |
scb-mcp | Swedish national statistics (PxWeb v2) |
worldbank-mcp | Governance (WGI), environment, social residue only — never economic context (use IMF CLI) |
Calling IMF from agentic workflows
tools:
bash: true
network:
allowed:
- www.imf.org
- api.imf.org
See analysis/imf/agentic-integration.md for the seven-step integration contract.