개요: MCP 생태계를 위한 8개의 고급 서버
이전 기사에서는 프로젝트 관리, 생산성 및 DevOps 전용 MCP 서버를 분석했습니다. 이 시리즈의 열한 번째 기사를 통해 우리는 다음과 같은 문제를 다룹니다. 8개의 고급 서버 완료 프로젝트의 아키텍처 Tech-MCP: 사고 관리, 품질 게이트, 워크플로 조정, 액세스 제어, 결정 로그, 서버 간 분석, 서비스 레지스트리 및 집계 대시보드.
이러한 서버는 생태계의 가장 정교한 수준을 나타냅니다. 그들은 독립적으로 운영되지는 않지만, 위해 설계된 서로 협력하다 EventBus를 통해 클라이언트매니저, 이벤트에 자동으로 대응할 수 있는 통합 시스템 구축, 보안 정책 적용, 코드 품질을 확인하고 복잡한 워크플로를 조정합니다.
이 기사에서 배울 내용
- 6가지 전용 도구를 사용하여 사고의 전체 수명 주기를 관리하는 방법
- 상태 및 링크를 사용하여 ADR(아키텍처 결정 기록)을 기록하고 추적하는 방법
- 허용/거부 정책을 사용하여 RBAC 액세스 제어를 구현하는 방법
- 비교 연산자를 사용하여 메트릭 기반 품질 게이트를 정의하고 평가하는 방법
- ClientManager를 통해 서버 간 실행으로 이벤트 중심 워크플로를 조정하는 방법
- 통찰력 엔진을 사용하여 모든 서버의 분석 및 지표를 집계하는 방법
- 레지스트리를 사용하여 서비스 검색 및 상태 모니터링을 구현하는 방법
- 여러 소스의 캐싱 및 데이터를 사용하여 집계된 대시보드를 노출하는 방법
고급 서버 맵
각 서버를 자세히 분석하기 전에 역할에 대한 간략한 개요는 다음과 같습니다. 8개의 고급 서버 간의 관계는 다음과 같습니다.
8개의 고급 서버 요약
| 섬기는 사람 | 역할 | 도구 | 이벤트버스 | 클라이언트매니저 |
|---|---|---|---|---|
| 사고 관리자 | 사고 수명주기 관리 | 6 | 이벤트를 생산합니다 | No |
| 의사결정 로그 | 아키텍처 결정 기록 | 5 | 이벤트를 생산합니다 | No |
| 액세스 정책 | RBAC/ABAC 액세스 제어 | 5 | 이벤트를 생산합니다 | No |
| 품질 게이트 | 측정 기준 기반 품질 게이트 | 4 | 이벤트를 생산합니다 | No |
| 워크플로 조정자 | 이벤트 기반 워크플로우 조정 | 5 | 생산 + 소비 | Si |
| 통찰력 엔진 | 분석 및 서버 간 상관 관계 | 4 | No | Si |
| mcp-레지스트리 | 서비스 검색 및 상태 확인 | 4 | 이벤트를 생산합니다 | No |
| 대시보드 API | 다중 서버 집계 대시보드 | 4 | No | Si |
1. 사고 관리자: 사고 수명주기 관리
서버 사고 관리자 사고의 전체 수명주기를 관리합니다: 시작부터 조사, 완화 및 자동 사후 생성을 통해 문제를 해결합니다. 각 상태 전환은 상세한 타임라인에서 추적되며 중요한 이벤트가 게시됩니다. EventBus에서 다른 서버의 자동 반응을 허용합니다.
사고의 수명주기
사고는 관리 프로세스에서 정확한 의미를 갖는 다섯 가지 상태를 거칩니다.
[open] ──────> [investigating] ──────> [mitigating] ──────> [resolved] ──────> [postmortem]
│ │ │ │
│ │ │ └── Genera report
│ │ └── Impatto ridotto post-mortem
│ └── Root cause in analisi
└── Incidente appena aperto
Eventi pubblicati:
incident:opened → Quando un incidente viene aperto
incident:escalated → Quando la severity cambia
incident:resolved → Quando l'incidente viene risolto
6가지 사고 관리자 도구
사용 가능한 도구
| 도구 | 설명 | 주요 매개변수 |
|---|---|---|
open-incident |
새로운 사건이 열렸습니다 | title, severity, description, affectedSystems |
update-incident |
상태 업데이트 및/또는 메모 추가 | id, status, note |
add-timeline-entry |
타임라인에 항목을 추가합니다. | incidentId, description, source |
resolve-incident |
요약 및 근본 원인으로 해결 | id, resolution, rootCause |
generate-postmortem |
형식화된 사후 보고서 생성 | id |
list-incidents |
필터를 사용하여 사건 나열 | status, severity, limit |
예: 사고 시작 및 해결
중대한 사건의 발생부터 해결까지의 전체 흐름은 다음과 같습니다. EventBus에 이벤트 게시:
// 1. Apertura dell'incidente
server.tool('open-incident', 'Open a new incident...', {
title: z.string().describe('Short title of the incident'),
severity: z.enum(['critical', 'high', 'medium', 'low'])
.describe('Incident severity level'),
description: z.string().describe('Detailed description'),
affectedSystems: z.array(z.string()).optional()
.describe('List of affected systems or services'),
}, async ({ title, severity, description, affectedSystems }) => {
const incident = store.openIncident({
title, severity, description, affectedSystems
});
// Pubblicazione evento sull'EventBus
eventBus?.publish('incident:opened', {
incidentId: String(incident.id),
title: incident.title,
severity: incident.severity,
affectedSystems: incident.affectedSystems,
});
return {
content: [{ type: 'text', text: JSON.stringify(incident, null, 2) }]
};
});
사건이 해결되면 도구는 resolve-incident 자동으로 계산하다
사고 기간을 파악하고 사후 분석을 위한 데이터를 생성합니다.
// 2. Risoluzione con root cause analysis
server.tool('resolve-incident', '...', {
id: z.number().int().positive(),
resolution: z.string().describe('Summary of how it was resolved'),
rootCause: z.string().optional().describe('Root cause analysis'),
}, async ({ id, resolution, rootCause }) => {
const resolved = store.resolveIncident(id, resolution, rootCause);
const postmortem = store.generatePostmortemData(id);
const durationMinutes = postmortem?.durationMinutes ?? 0;
eventBus?.publish('incident:resolved', {
incidentId: String(id),
title: resolved.title,
resolution,
durationMinutes,
});
return {
content: [{ type: 'text', text: JSON.stringify(resolved, null, 2) }]
};
});
데이터 모델: 사건 및 타임라인
SQLite 저장소는 두 개의 테이블을 관리합니다. incidents 메인 데이터 e의 경우
incident_timeline 수명 주기 동안 각 이벤트를 추적하려면 다음을 수행하세요.
interface Incident {
id: number;
title: string;
severity: string; // 'critical' | 'high' | 'medium' | 'low'
description: string;
status: string; // 'open' | 'investigating' | 'mitigating' | 'resolved' | 'postmortem'
affectedSystems: string[];
resolution: string | null;
rootCause: string | null;
createdAt: string;
resolvedAt: string | null;
}
interface TimelineEntry {
id: number;
incidentId: number;
description: string;
source: string | null; // es. 'monitoring', 'engineer', 'automated'
timestamp: string;
}
다른 서버와의 협업
사고 관리자는 협업 핸들러를 통해 다른 서버의 이벤트도 수신합니다.
예를 들어, 이벤트 perf:bottleneck-found 성능 프로파일러 또는 이벤트에서
cicd:build-failed CI/CD 모니터에서 자동으로 항목을 추가할 수 있습니다.
관련 사건의 타임라인으로 이동합니다.
2. 결정 로그: 아키텍처 결정 기록
서버 의사결정 로그 관리를 구현합니다. ADR(아키텍처 결정 기록), 프로젝트의 아키텍처 결정을 문서화하기 위한 통합 패턴입니다. 모든 결정 상황, 고려된 대안, 예상되는 결과와 함께 기록됩니다. 그리고 현재 상태.
결정의 상태
결정은 다음과 같은 네 가지 상태로 구성된 수명 주기를 거칩니다.
[proposed] ──────> [accepted] ──────> [deprecated]
│
└──────> [superseded] ← (sostituita da una nuova decisione)
Eventi pubblicati:
decision:created → Quando una nuova decisione viene registrata
decision:superseded → Quando una decisione viene sostituita
5가지 결정 로그 도구
사용 가능한 도구
| 도구 | 설명 | 주요 매개변수 |
|---|---|---|
record-decision |
새 ADR 등록 | title, context, decision, alternatives, status |
list-decisions |
기록된 결정을 나열합니다. | 선택적 필터 |
get-decision |
ID로 결정 검색 | id |
supersede-decision |
하나의 결정을 새로운 결정으로 대체합니다. | id, supersededBy |
link-decision |
티켓, 커밋 또는 영향에 대한 링크 | decisionId, linkType, targetId |
예: ADR 등록 및 연결
아키텍처 결정은 컨텍스트, 대안 및 결과와 함께 기록됩니다. 그런 다음 관련 티켓 및 커밋에 연결됩니다.
// Registrazione di una decisione
server.tool('record-decision', '...', {
title: z.string().describe('Short title, e.g. "Use PostgreSQL for analytics"'),
context: z.string().describe('Context and problem statement'),
decision: z.string().describe('The decision that was made'),
alternatives: z.array(z.string()).optional()
.describe('Alternative options considered'),
consequences: z.string().optional()
.describe('Expected consequences'),
status: z.enum(['proposed', 'accepted', 'deprecated', 'superseded'])
.optional().default('proposed'),
relatedTickets: z.array(z.string()).optional()
.describe('Related ticket IDs, e.g. ["PROJ-123"]'),
}, async (args) => {
const record = store.recordDecision(args);
eventBus?.publish('decision:created', {
decisionId: String(record.id),
title: record.title,
status: record.status,
});
return { content: [{ type: 'text', text: JSON.stringify(record, null, 2) }] };
});
// Collegamento a ticket e commit
server.tool('link-decision', '...', {
decisionId: z.number().int().positive(),
linkType: z.enum(['ticket', 'commit', 'impact', 'related']),
targetId: z.string().describe('Ticket ID, commit hash, etc.'),
description: z.string().optional(),
}, async ({ decisionId, linkType, targetId, description }) => {
const link = store.linkDecision({ decisionId, linkType, targetId, description });
return { content: [{ type: 'text', text: JSON.stringify(link, null, 2) }] };
});
데이터 모델: 의사결정 및 연결
interface Decision {
id: number;
title: string;
context: string;
decision: string;
alternatives: string[];
consequences: string;
status: string; // 'proposed' | 'accepted' | 'deprecated' | 'superseded'
relatedTickets: string[];
supersededBy: number | null;
createdAt: string;
updatedAt: string;
}
interface DecisionLink {
id: number;
decisionId: number;
linkType: string; // 'ticket' | 'commit' | 'impact' | 'related'
targetId: string;
description: string | null;
createdAt: string;
}
3. 액세스 정책: RBAC 액세스 제어
서버 액세스 정책 접근 제어 시스템을 구현합니다.
RBAC/ABAC (역할 기반/속성 기반 접근 제어) 횡단적으로 작동
MCP 생태계의 모든 서버와 도구에서. 액세스 정책을 정의할 수 있습니다.
사실상 allow o deny, 사용자에게 역할을 할당하고 확인
도구를 실행하기 전에 권한을 부여합니다. 각 확인은 감사 로그에 기록됩니다.
5가지 액세스 정책 도구
사용 가능한 도구
| 도구 | 설명 | 주요 매개변수 |
|---|---|---|
create-policy |
새 액세스 정책 만들기 | name, effect, rules[] |
check-access |
사용자에게 액세스 권한이 있는지 확인 | userId, server, tool |
list-policies |
활성 정책 나열 | 아무도 |
assign-role |
사용자에게 역할 할당 | userId, roleName |
audit-access |
감사 로그 검색 | userId, server, limit |
예: RBAC 정책 정의
정책은 특정 서버 및 도구에 액세스할 수 있는 역할을 정의합니다.
효과는 다음과 같습니다. allow (허용) 또는 deny (부인하다).
규칙은 와일드카드를 사용합니다. * 모든 서버 또는 도구를 나타냅니다.
// Creazione di una policy: solo gli admin possono aprire incidenti
server.tool('create-policy', '...', {
name: z.string().describe('Unique name for the policy'),
effect: z.enum(['allow', 'deny']),
rules: z.array(z.object({
server: z.string().describe('Server name or "*" for all'),
tool: z.string().optional().describe('Tool name, omit for all'),
roles: z.array(z.string()).describe('Roles this rule applies to'),
})),
}, async ({ name, effect, rules }) => {
const policy = store.createPolicy({ name, effect, rules });
eventBus?.publish('access:policy-updated', {
policyId: String(policy.id),
name: policy.name,
effect: policy.effect,
});
return { content: [{ type: 'text', text: JSON.stringify(policy, null, 2) }] };
});
정책의 예
고위 개발자에게 액세스 권한을 부여하는 정책이 구성되는 방식은 다음과 같습니다. 특정 서버 및 도구의 경우:
{
"name": "senior-dev-policy",
"effect": "allow",
"rules": [
{
"server": "scrum-board",
"roles": ["senior-dev", "tech-lead"]
},
{
"server": "incident-manager",
"tool": "open-incident",
"roles": ["senior-dev", "tech-lead", "ops"]
},
{
"server": "quality-gate",
"tool": "evaluate-gate",
"roles": ["senior-dev"]
}
]
}
액세스 확인 및 감사 로그
도구 check-access 권한을 확인하고 각 권한을 자동으로 기록합니다.
감사 로그를 확인해 보세요. 액세스가 거부되면 이벤트가 게시됩니다.
access:denied 이벤트버스에서:
// Verifica accesso con audit automatico
server.tool('check-access', '...', {
userId: z.string(),
server: z.string(),
tool: z.string().optional(),
}, async ({ userId, server: targetServer, tool }) => {
const result = store.checkAccess(userId, targetServer, tool);
// Log automatico nell'audit log
store.logAccess(userId, targetServer, tool ?? '*',
result.allowed ? 'allowed' : 'denied', result.reason);
// Evento per accessi negati
if (!result.allowed) {
eventBus?.publish('access:denied', {
userId, server: targetServer,
tool: tool ?? '*', reason: result.reason,
});
}
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
});
데이터 모델: 정책, 역할 및 감사
SQLite 저장소는 4개의 테이블을 관리합니다. policies 액세스 정책의 경우
roles 역할 정의를 위해 role_assignments 협회를 위해
사용자 역할 e audit_log 각 액세스 확인을 추적합니다.
이 구조를 사용하면 규정 준수 및 디버깅을 위한 전체 액세스 기록을 재구성할 수 있습니다.
4. 품질 게이트(Quality Gate): 측정항목을 기반으로 한 품질 검사
서버 품질 게이트 정의하고 평가할 수 있습니다. 품질 게이트 정량적 지표를 기반으로 합니다. 각 게이트에는 측정항목, 비교 연산자가 포함된 체크리스트가 포함되어 있습니다. 그리고 문턱. 게이트가 평가되면 결과(통과/실패)가 EventBus에 게시됩니다. 자동 워크플로를 활성화합니다.
4가지 품질 게이트 도구
사용 가능한 도구
| 도구 | 설명 | 주요 매개변수 |
|---|---|---|
define-gate |
새로운 품질 게이트를 정의합니다 | name, projectName, checks[] |
evaluate-gate |
실제 측정항목으로 게이트 평가 | gateId, metrics |
list-gates |
정의된 게이트를 나열합니다. | 아무도 |
get-gate-history |
평가 내역 | gateId |
규칙을 통한 품질 게이트 정의
품질 게이트는 일련의 검사를 정의하며 각 검사에는 측정항목, 연산자가 포함됩니다.
비교 및 임계값. 지원되는 연산자는 다음과 같습니다. >=, <=,
>, <, == e !=.
// Definizione di un quality gate
server.tool('define-gate', '...', {
name: z.string().describe('Name of the quality gate'),
projectName: z.string().optional(),
checks: z.array(z.object({
metric: z.string().describe('Metric name, e.g. "coverage"'),
operator: z.enum(['>=', '<=', '>', '<', '==', '!=']),
threshold: z.number().describe('Threshold value'),
})),
}, async ({ name, projectName, checks }) => {
const gate = store.defineGate({ name, projectName, checks });
return { content: [{ type: 'text', text: JSON.stringify(gate, null, 2) }] };
});
예: 배포를 위한 품질 게이트 구성
{
"name": "deploy-readiness",
"projectName": "Tech-MCP",
"checks": [
{ "metric": "coverage", "operator": ">=", "threshold": 80 },
{ "metric": "complexity", "operator": "<=", "threshold": 15 },
{ "metric": "bugs", "operator": "==", "threshold": 0 },
{ "metric": "duplication", "operator": "<=", "threshold": 3 },
{ "metric": "buildTime", "operator": "<", "threshold": 300 }
]
}
평가 및 이벤트
프로젝트의 실제 지표를 사용하여 게이트를 평가하면 결과에 따라 결정됩니다.
어떤 이벤트가 게시되었는지. 모든 지표가 검사를 만족하면 발행됩니다.
quality:gate-passed; 그렇지 않으면 quality:gate-failed 실패에 대한 세부정보:
// Valutazione del gate
server.tool('evaluate-gate', '...', {
gateId: z.number().int().positive(),
metrics: z.record(z.string(), z.number())
.describe('Map of metric names to current values'),
}, async ({ gateId, metrics }) => {
const evaluation = store.evaluateGate(gateId, metrics);
const gate = store.getGate(gateId);
if (evaluation.passed) {
eventBus?.publish('quality:gate-passed', {
gateName: gate?.name ?? String(gateId),
project: gate?.projectName ?? '',
results: evaluation.results,
});
} else {
eventBus?.publish('quality:gate-failed', {
gateName: gate?.name ?? String(gateId),
project: gate?.projectName ?? '',
failures: evaluation.failures,
});
}
return { content: [{ type: 'text', text: JSON.stringify(evaluation, null, 2) }] };
});
CI/CD 협업
품질 게이트는 CI/CD 모니터의 이벤트를 수신합니다. 이벤트가 있을 때 cicd:pipeline-completed
게시되면 서버는 프로젝트와 관련된 품질 게이트를 자동으로 평가할 수 있습니다.
마찬가지로 이벤트도 test:coverage-report 인증을 활성화할 수 있습니다
코드 적용 범위와 관련된 게이트.
5. 워크플로 오케스트레이터: 이벤트 중심 자동화
Il 워크플로 조정자 전체 생태계에서 가장 정교한 서버입니다.
오케스트레이션 엔진 구현 이벤트 중심 이를 통해 정의할 수 있습니다.
각각 MCP 서버의 도구를 호출하는 순차적 단계로 구성된 워크플로
걸쳐서 다른 클라이언트매니저. 워크플로가 자동으로 활성화됩니다.
EventBus에 게시된 이벤트에서 또는 도구를 통해 수동으로 trigger-workflow.
5가지 워크플로 조정 도구
사용 가능한 도구
| 도구 | 설명 | 주요 매개변수 |
|---|---|---|
create-workflow |
이벤트 기반 워크플로 만들기 | name, triggerEvent, steps[] |
list-workflows |
정의된 워크플로를 나열합니다. | 아무도 |
trigger-workflow |
워크플로를 수동으로 시작 | workflowId, payload |
get-workflow-run |
실행 세부정보 | runId |
toggle-workflow |
워크플로 활성화/비활성화 | workflowId, active |
단계 간 서버를 사용한 워크플로우 정의
워크플로는 트리거 이벤트, 선택적 조건 및 순서가 지정된 시퀀스를 정의합니다.
단계. 각 단계에서는 대상 서버, 호출할 도구 및 인수를 지정합니다.
인수 지원 템플릿 {{payload.field}} e
{{steps[N].result.field}} 단계 간에 데이터를 전달하려면 다음을 수행하세요.
// Creazione di un workflow
server.tool('create-workflow', '...', {
name: z.string(),
description: z.string().optional(),
triggerEvent: z.string()
.describe('Event that triggers this workflow, e.g. "incident:opened"'),
triggerConditions: z.record(z.unknown()).optional()
.describe('Conditions to match against the event payload'),
steps: z.array(z.object({
server: z.string().describe('Target MCP server name'),
tool: z.string().describe('Tool to invoke'),
arguments: z.record(z.unknown()).optional()
.describe('Arguments with { {payload.field} } template support'),
})),
}, async (args) => {
const workflow = store.createWorkflow(args);
return { content: [{ type: 'text', text: JSON.stringify(workflow, null, 2) }] };
});
예: 중대한 사고에 대한 자동 워크플로
심각도가 있는 인시던트가 열릴 때 활성화되는 전체 워크플로는 다음과 같습니다.
critical. 워크플로는 세 가지 서버에서 세 단계를 수행합니다.
{
"name": "critical-incident-response",
"description": "Automated response for critical incidents",
"triggerEvent": "incident:opened",
"triggerConditions": {
"severity": "critical"
},
"steps": [
{
"server": "decision-log",
"tool": "record-decision",
"arguments": {
"title": "Emergency: {{payload.title}}",
"context": "Critical incident opened affecting {{payload.affectedSystems}}",
"decision": "Activating emergency response protocol",
"status": "accepted"
}
},
{
"server": "quality-gate",
"tool": "evaluate-gate",
"arguments": {
"gateId": 1,
"metrics": {
"activeIncidents": 1,
"severity": 4
}
}
},
{
"server": "incident-manager",
"tool": "add-timeline-entry",
"arguments": {
"incidentId": "{{payload.incidentId}}",
"description": "Automated response workflow triggered",
"source": "workflow-orchestrator"
}
}
]
}
WorkflowEngine: 실행 및 템플릿 확인
워크플로 조정자의 핵심은 워크플로우엔진, 해상도를 처리합니다. 템플릿의 트리거 조건 평가 및 단계의 순차적 실행 ClientManager를 통해:
class WorkflowEngine {
constructor(
private store: WorkflowStore,
private clientManager?: McpClientManager,
private eventBus?: EventBus,
) {}
// Risolve template come {{payload.title}} e {{steps[0].result.id}}
resolveTemplates(
template: Record<string, unknown>,
context: {
payload: Record<string, unknown>;
steps: Array<{ result: Record<string, unknown> | null }>;
}
): Record<string, unknown>;
// Valuta condizioni trigger: ogni chiave deve matchare il payload
evaluateTrigger(
conditions: Record<string, unknown>,
payload: Record<string, unknown>
): boolean;
// Esegue il workflow step per step via ClientManager
async executeWorkflow(
workflow: Workflow,
triggerPayload: Record<string, unknown>
): Promise<WorkflowRunRecord>;
// Gestisce eventi: trova workflow attivi e li esegue
async handleEvent(event: string, payload: unknown): Promise<void>;
}
EventBus 와일드카드 패턴
워크플로 조정자의 협업 핸들러는 다음 패턴을 사용합니다. * 에 대한
구독하다 모든 이벤트 이벤트버스의 수신된 각 이벤트에 대해
엔진은 활성 워크플로를 검색합니다. triggerEvent 이벤트에 해당합니다
그리고 누구의 triggerConditions 페이로드에 만족합니다. 이를 통해
서버 코드를 수정하지 않고도 반응형 자동화를 생성할 수 있습니다.
데이터 모델: 워크플로우, 실행 및 단계
interface Workflow {
id: number;
name: string;
description: string | null;
triggerEvent: string;
triggerConditions: Record<string, unknown>;
steps: {
server: string;
tool: string;
arguments: Record<string, unknown>;
}[];
active: boolean;
createdAt: string;
updatedAt: string;
}
interface WorkflowRunRecord {
id: number;
workflowId: number;
status: string; // 'running' | 'completed' | 'failed'
triggerPayload: Record<string, unknown>;
error: string | null;
startedAt: string;
completedAt: string | null;
durationMs: number | null;
}
6. 통찰력 엔진: 서버 간 분석
서버 통찰력 엔진 생태계의 지능 수준을 나타냅니다. 사용 클라이언트매니저 사용 가능한 모든 서버에서 데이터를 수집하고, 다양한 소스의 측정항목을 상호 연결하고 프로젝트 상태에 대한 집계 보기를 표시합니다. 그만큼 상관 엔진 내부에서는 측정항목을 소스 서버에 매핑하고 관리합니다. 서버를 사용할 수 없을 때의 점진적인 성능 저하.
4가지 통찰력 엔진 도구
사용 가능한 도구
| 도구 | 설명 | 주요 매개변수 |
|---|---|---|
query-insight |
자연어 쿼리 | question, forceRefresh |
correlate-metrics |
서로 다른 서버의 측정항목을 연관시키세요. | metrics[], period |
explain-trend |
측정항목의 추세 설명 | metric, direction |
health-dashboard |
프로젝트 상태 대시보드 | forceRefresh |
CorrelationEngine: 메트릭-서버 매핑
통찰력 엔진의 핵심은 CorrelationEngine, 지도를 유지 관리하는
사용 가능한 측정항목과 이를 제공하는 서버의 내부입니다. 요청 시
상관 관계에 따라 엔진은 ClientManager를 통해 적절한 서버를 호출합니다.
결과를 집계합니다.
class CorrelationEngine {
// Mappatura metrica -> server/tool
private metricMap = {
'velocity': { server: 'agile-metrics', tool: 'calculate-velocity' },
'time-logged': { server: 'time-tracking', tool: 'get-timesheet' },
'budget-spent': { server: 'project-economics', tool: 'get-budget-status' },
};
// Chiamata sicura: ritorna null se il server non e disponibile
async safeCall(server: string, tool: string, args = {})
: Promise<Record<string, unknown> | null>;
// Correlazione di metriche multiple
async correlateMetrics(metrics: string[])
: Promise<{ metrics: Record; dataSources: Record; analyzedAt: string }>;
// Dashboard salute del progetto con health score
async getProjectHealth()
: Promise<{ healthScore: number; velocity; timeTracking; budget; dataSources }>;
// Query basata su keyword matching
async queryInsight(question: string)
: Promise<{ question; relevantMetrics; data; generatedAt }>;
}
지능형 캐싱
통찰력 엔진은 다음을 통해 내부 캐싱 시스템을 사용합니다.InsightStore.
응답은 분석 유형과 쿼리로 구성된 키와 함께 저장됩니다.
매개변수 forceRefresh 필요한 경우 캐시를 우회할 수 있습니다.
도구 health-dashboard 균형을 맞추려면 300초의 TTL을 사용하세요.
데이터 신선도 및 성능.
7. MCP 레지스트리: 서비스 검색 및 상태 모니터링
서버 mcp-레지스트리 그것은 다음과 같이 작동합니다 서비스 레지스트리 MCP 생태계를 위한 것입니다. 각 서버는 자체 URL, 전송 프로토콜로 등록할 수 있습니다. 그리고 능력 목록. 레지스트리는 주기적인 상태 확인을 지원하고 이벤트를 게시합니다. 서버를 사용할 수 없게 된 경우.
MCP 레지스트리의 4가지 도구
사용 가능한 도구
| 도구 | 설명 | 주요 매개변수 |
|---|---|---|
register-server |
새 서버 등록 | name, url, transport, capabilities |
discover-servers |
등록된 서버 검색 | status, transport |
health-check |
건강검진을 실시합니다 | serverId |
get-capabilities |
서버의 기능을 가져옵니다. | serverId |
서버 등록 및 검색
// Registrazione di un server nell'ecosistema
server.tool('register-server', '...', {
name: z.string().describe('Unique name of the MCP server'),
url: z.string().describe('URL or endpoint'),
transport: z.enum(['stdio', 'http', 'in-memory'])
.optional().default('stdio'),
capabilities: z.array(z.string()).optional()
.describe('List of capabilities'),
}, async ({ name, url, transport, capabilities }) => {
const record = store.registerServer({ name, url, transport, capabilities });
eventBus?.publish('registry:server-registered', {
serverName: record.name,
url: record.url,
capabilities: record.capabilities,
});
return { content: [{ type: 'text', text: JSON.stringify(record, null, 2) }] };
});
// Discovery con filtri per stato e trasporto
server.tool('discover-servers', '...', {
status: z.enum(['healthy', 'unhealthy', 'unknown']).optional(),
transport: z.enum(['stdio', 'http', 'in-memory']).optional(),
}, async ({ status, transport }) => {
const servers = store.listServers({ status, transport });
return { content: [{ type: 'text', text: JSON.stringify(servers, null, 2) }] };
});
상태 점검 및 모니터링
도구 health-check 등록된 서버에 대한 상태 확인을 수행합니다.
서버를 사용할 수 없는 경우 이벤트가 게시됩니다. registry:server-unhealthy
이벤트버스에서:
// Health check con pubblicazione eventi
server.tool('health-check', '...', {
serverId: z.number().int().positive(),
}, async ({ serverId }) => {
const srv = store.getServer(serverId);
const responseTimeMs = /* misurazione tempo risposta */;
const status = responseTimeMs > 450 ? 'unhealthy' : 'healthy';
const healthCheck = store.recordHealthCheck({
serverId, status, responseTimeMs,
error: status === 'unhealthy' ? 'Timeout' : undefined,
});
if (status === 'unhealthy') {
eventBus?.publish('registry:server-unhealthy', {
serverName: srv.name,
lastHealthy: srv.lastHealthCheck ?? srv.createdAt,
error: 'Health check failed',
});
}
return { content: [{ type: 'text', text: JSON.stringify(healthCheck, null, 2) }] };
});
8. API 대시보드: 다중 서버 집계
서버 대시보드 API 얻을 수 있는 통합 액세스 포인트 역할을 합니다. 전체 생태계에 대한 종합적인 시각을 제공합니다. 사용 클라이언트매니저 여러 서버에 동시에 쿼리(스크럼 보드, Agile-Metrics, 시간 추적, 프로젝트 경제, 의사결정 로그, 사고 관리자, 품질 게이트, 회고 관리자) 내장된 캐싱을 통해 일관된 형식으로 데이터를 제공합니다.
API 대시보드의 4가지 도구
사용 가능한 도구
| 도구 | 설명 | 쿼리된 서버 |
|---|---|---|
get-overview |
종합 프로젝트 개요 | 스크럼 보드, 애자일 측정, 시간 추적, 프로젝트 경제학 |
get-server-status |
등록된 서버 현황 | mcp-레지스트리 |
get-recent-activity |
최근 활동이 집계되었습니다. | 의사결정 로그, 사건 관리자, 회고 관리자 |
get-project-summary |
프로젝트의 전체 요약 | 모든 서버 사용 가능(7+) |
예: 집계 개요
도구 get-overview 4개의 서버에서 동시에 데이터를 수집합니다.
사용하여 Promise.all 성능을 극대화합니다. 각 서버마다,
데이터의 사용 가능 여부가 표시됩니다.
우아한 저하:
server.tool('get-overview', '...', {
forceRefresh: z.boolean().optional(),
}, async ({ forceRefresh }) => {
// Check cache (TTL 120 secondi)
if (!forceRefresh) {
const cached = store.getCached('overview', 'main');
if (cached) return { content: [{ type: 'text',
text: JSON.stringify({ ...cached, fromCache: true }, null, 2) }] };
}
// Aggregazione parallela da 4 server
const [scrumBoard, velocity, timesheet, budget] = await Promise.all([
safeCall(clientManager, 'scrum-board', 'list-sprints', {}),
safeCall(clientManager, 'agile-metrics', 'calculate-velocity', {...}),
safeCall(clientManager, 'time-tracking', 'get-timesheet', {}),
safeCall(clientManager, 'project-economics', 'get-budget-status', {...}),
]);
const overview = {
velocity: velocity ?? { status: 'unavailable' },
scrumBoard: scrumBoard ?? { status: 'unavailable' },
timeTracking: timesheet ?? { status: 'unavailable' },
budget: budget ?? { status: 'unavailable' },
dataSources: {
scrumBoard: scrumBoard ? 'available' : 'unavailable',
velocity: velocity ? 'available' : 'unavailable',
timeTracking: timesheet ? 'available' : 'unavailable',
budget: budget ? 'available' : 'unavailable',
},
generatedAt: new Date().toISOString(),
};
store.setCache('overview', 'main', overview, 120);
return { content: [{ type: 'text', text: JSON.stringify(overview, null, 2) }] };
});
프로젝트 요약: 완전한 비전
도구 get-project-summary 가장 완전한 집계를 나타냅니다.
비전을 생성하기 위해 사용 가능한 모든 서버를 동시에 쿼리하여
프로젝트의 360도:
// Aggregazione parallela da 7 server
const [velocity, timesheet, budget, decisions,
incidents, qualityGates, retros] = await Promise.all([
safeCall(clientManager, 'agile-metrics', 'calculate-velocity', {...}),
safeCall(clientManager, 'time-tracking', 'get-timesheet', {}),
safeCall(clientManager, 'project-economics', 'get-budget-status', {...}),
safeCall(clientManager, 'decision-log', 'list-decisions', {}),
safeCall(clientManager, 'incident-manager', 'list-incidents', {}),
safeCall(clientManager, 'quality-gate', 'list-gates', {}),
safeCall(clientManager, 'retrospective-manager', 'list-retros', {}),
]);
패턴 안전 호출 및 우아한 저하
Dashboard-API와 Insight-Engine 모두 이 패턴을 사용합니다. safeCall
서버 간 통신을 관리합니다. 서버를 사용할 수 없는 경우 통화는
반품 null 예외를 발생시키는 대신. 분야 dataSources
응답에는 각 서버의 가용성 상태가 표시되어 클라이언트가
어떤 데이터가 실제이고 어떤 데이터가 누락되었는지 파악합니다.
생태계 이벤트 맵
8개의 고급 서버는 EventBus를 통해 이벤트를 생성하고 소비합니다. 다음은 이러한 서버에서 생성된 이벤트의 전체 맵입니다.
고급 서버에서 게시한 이벤트
| 이벤트 | 소스 서버 | 메인 페이로드 |
|---|---|---|
incident:opened |
사고 관리자 | IncidentId, 제목, 심각도, 영향을 받는 시스템 |
incident:escalated |
사고 관리자 | IncidentId, PreviousSeverity, NewSeverity |
incident:resolved |
사고 관리자 | IncidentId, 제목, 해결 방법, 기간분 |
decision:created |
의사결정 로그 | 결정 ID, 제목, 상태 |
decision:superseded |
의사결정 로그 | 결정 ID, 대체자, 제목 |
access:policy-updated |
액세스 정책 | 정책 ID, 이름, 효과 |
access:denied |
액세스 정책 | 사용자 ID, 서버, 도구, 이유 |
quality:gate-passed |
품질 게이트 | GateName, 프로젝트, 결과 |
quality:gate-failed |
품질 게이트 | GateName, 프로젝트, 실패 |
workflow:triggered |
워크플로 조정자 | 워크플로 ID, 이름, TriggerBy |
workflow:completed |
워크플로 조정자 | WorkflowId, runId, 이름, 기간Ms |
workflow:failed |
워크플로 조정자 | WorkflowId, runId, 이름, 오류 |
registry:server-registered |
mcp-레지스트리 | 서버 이름, URL, 기능 |
registry:server-unhealthy |
mcp-레지스트리 | 서버 이름, lastHealthy, 오류 |
아키텍처: 자율 서버와 통합 서버
8개의 고급 서버는 두 가지 아키텍처 범주로 나뉩니다. 생태계의 나머지 부분과 상호 작용하는 방식에 따라:
아키텍처 비교
| 범주 | 섬기는 사람 | 특성 |
|---|---|---|
| 자발적인 | 사고 관리자, 의사결정 로그, 액세스 정책, 품질 게이트 | 자신의 도메인을 관리하고 이벤트를 생성하며 ClientManager가 필요하지 않습니다. |
| 완성 | 워크플로 조정자, 통찰력 엔진, 대시보드-api, mcp-registry | 다른 서버의 데이터를 집계하고 서버 간 통신을 위해 ClientManager가 필요합니다. |
서버 자발적인 그들은 또한 고립되어 기능할 수도 있습니다. 그들은 스스로를 관리합니다. SQLite 데이터베이스를 사용하고 다른 서버에 의존하지 않고 EventBus에 이벤트를 게시합니다. 서버 완성 생태계의 맥락에서 작동하도록 설계되었습니다. 완료하고 ClientManager를 사용하여 다른 서버를 쿼리하고 데이터를 집계합니다.
결론
8개의 고급 서버가 프로젝트 아키텍처를 완성합니다. Tech-MCP, 생태계를 기업 수준의 정교함으로 끌어올립니다. 사고관리부터 품질 보증, 액세스 제어부터 워크플로 조정까지, 모든 서버 전체 플랫폼에 특정 도메인을 기여합니다.
나타나는 패턴은 다음과 같습니다. 이벤트 중심 분산 시스템: 자율 서버는 자체 도메인을 관리하고 이벤트를 게시합니다. 워크플로 조정자 서버 간 자동화 및 집계 서버를 실행하여 이벤트에 반응합니다. (insight-engine, Dashboard-api)는 전체 생태계에 대한 통합 보기를 제공합니다.
다음 글에서는 이에 대해 더 자세히 알아보겠습니다. 서버 간 협업: 생태계의 31개 MCP 서버가 EventBus를 통해 서로 통신하는 방법, ClientManager가 서버 간 호출을 활성화하는 방법 및 협업 패턴 이를 통해 간단한 구성 요소부터 시작하여 복잡한 자동화를 구축할 수 있습니다.
모든 서버의 전체 코드는 저장소에서 사용할 수 있습니다. GitHub의 Tech-MCP.







