SpecSync: Keeping Code and Contracts in Sync
The Problem That Inspired Us
We've all been there: you commit code that looks perfect, tests pass, CI is green—but three days later, someone discovers your new endpoint isn't documented, your API call targets a non-existent backend route, or your tests don't actually cover the feature you just shipped.
Drift happens. And it happens silently.
Even worse, in microservices architectures, drift happens across repositories. Your frontend team updates their API calls, but the backend team changed the endpoint signature last week. Nobody knows until production breaks.
I built SpecSync to solve this at the source: at commit time, before drift enters your codebase.
What I Built
SpecSync is a two-part system that leverages Kiro's Model Context Protocol (MCP) to provide intelligent, automated validation:
Part 1: SpecSync Core - Single-Repo Validation
A commit-time validation system that ensures:
- Specs define what you're building
- Code implements the spec
- Tests verify the implementation
- Docs explain the API
When you commit, SpecSync validates all four are aligned. If they're not, it either:
- Blocks the commit (strict mode)
- Generates remediation tasks (task mode)
- Auto-fixes drift (semi-auto mode with Kiro)
Part 2: Bridge - Cross-Repo Contract Sync
A git-based contract synchronization system that:
- Extracts API contracts from provider repos (backends)
- Syncs contracts to consumer repos (frontends) via git
- Validates API calls against cached contracts
- Detects drift before integration breaks
Bridge works offline (uses cached contracts) and syncs in parallel (multiple dependencies at once).
How I Built It
Architecture
┌─────────────────────────────────────────────────────────┐
│ Kiro (MCP Client) │
└─────────────────────────────────────────────────────────┘
│
│ MCP Protocol
▼
┌─────────────────────────────────────────────────────────┐
│ SpecSync MCP Server (TypeScript) │
│ Tools: git_get_staged_diff, bridge_*, validate_* │
└─────────────────────────────────────────────────────────┘
│
┌──────────┴──────────┐
▼ ▼
┌───────────────────┐ ┌──────────────────┐
│ SpecSync Core │ │ Bridge System │
│ (Python) │ │ (Python) │
│ │ │ │
│ • Validator │ │ • Extractor │
│ • Drift Detector │ │ • Sync Engine │
│ • Test Analyzer │ │ • Drift Detector│
│ • Doc Analyzer │ │ • CLI │
└───────────────────┘ └──────────────────┘
Key Technologies
MCP Integration:
- Built custom MCP server in TypeScript using
@modelcontextprotocol/sdk - Exposed 9 tools to Kiro for validation and contract sync (including
bridge_auto_sync) - Enabled Kiro to orchestrate complex validation workflows
Python Backend:
- AST parsing for code analysis (endpoints, API calls, models)
- YAML for contract serialization
- Git subprocess for cross-repo sync
- ThreadPoolExecutor for parallel sync (max 5 concurrent)
- Hypothesis for property-based testing
Validation Logic:
- Steering rules (
.kiro/steering/rules.md) define correlation patterns - File correlation:
backend/handlers/*.py→.kiro/specs/app.yaml - Multi-analyzer architecture: drift, test coverage, documentation
- Configurable blocking vs. task generation
Bridge Sync:
- Git-based:
git clone --depth 1for efficiency - Offline fallback: uses cached contracts when sync fails
- Contract diff: detects added/removed/modified endpoints
- Auto-detection: scans code to determine provider vs. consumer role
- Auto-sync: configurable intervals with silent mode and notifications
- Interactive wizard: one-command setup with auto-detection and guided prompts
What I Learned
1. MCP is Powerful for Agentic Workflows
By exposing validation as MCP tools, I let Kiro:
- Decide when to validate (pre-commit, on-demand, etc.)
- Orchestrate complex workflows (sync → validate → fix)
- Provide context-aware suggestions
This is way more flexible than a rigid git hook.
2. Property-Based Testing Catches Edge Cases
I used Hypothesis to generate random contracts, endpoints, and configurations. This caught bugs I never would have found with example-based tests:
- Duplicate endpoint handling
- Unicode in contract paths
- Empty endpoint lists
- Concurrent sync race conditions
3. Offline-First Design Matters
Bridge caches contracts locally, so validation works even when:
- Network is down
- Dependency repo is private
- CI environment has no git access
This made the system way more reliable.
4. Cross-Repo Sync is Hard
Challenges I solved:
- Temporary directory cleanup: Used
try/finallyto ensure cleanup even on failure - Parallel sync deadlocks: Limited to 5 concurrent syncs
- Git credential handling: Relied on system git config (no credential storage)
- Contract versioning: Used timestamps and diff detection
Challenges I Faced
Challenge 1: AST Parsing Complexity
Problem: FastAPI uses decorators like @app.get("/users"), but I also needed to support @router.get, async functions, and various parameter types.
Solution: Built a flexible AST walker that handles:
- Both
FunctionDefandAsyncFunctionDef - Multiple decorator patterns (
app,router,api,blueprint) - Type annotations for parameters and return types
Challenge 2: Git Operations in Python
Problem: Python's subprocess for git is error-prone (encoding issues, timeouts, cleanup).
Solution:
- Used
capture_output=True, text=True, encoding='utf-8', errors='replace' - Implemented timeout (60s) and retry logic
- Shallow clones (
--depth 1) for speed - Proper temp directory cleanup with
shutil.rmtree
Challenge 3: Making Validation Non-Blocking
Problem: Developers hate blocked commits. But I need to catch drift.
Solution: Three modes:
- Blocking mode: Fail commit on drift (strict teams)
- Task mode: Generate
.kiro/specs/*/remediation-tasks.md(flexible teams) - Semi-auto mode: Kiro fixes drift automatically after commit (AI-assisted teams)
Configurable via .kiro/settings/specsync.json.
Challenge 4: Language Support Scope
Problem: Supporting multiple languages (Python, TypeScript, Go, Java) would require different AST parsers, framework patterns, and testing strategies.
Solution:
- Focused on Python first to deliver a working system within the hackathon timeline
- Built extensible architecture that makes adding languages straightforward
- Python covers FastAPI, Flask, Django—a large portion of modern APIs
- Roadmap includes TypeScript/JavaScript (Express, NestJS) as next priority
This trade-off let us build a complete, tested system rather than a half-working multi-language prototype.
Challenge 5: Testing Cross-Repo Sync
Problem: Hard to test git-based sync without real repos.
Solution:
- Integration tests use temporary git repos
- Mock git operations for unit tests
- Property-based tests for contract diff logic
- Manual testing checklist for end-to-end validation
Technical Highlights
Property-Based Test Example
from hypothesis import given, strategies as st
@given(
old_contract=contract_strategy(),
new_contract=contract_strategy()
)
def test_contract_diff_is_symmetric(old_contract, new_contract):
"""Property: Diff should detect all changes between any two contracts."""
diff = compare_contracts(old_contract, new_contract)
# If contracts are identical, diff should be empty
if old_contract == new_contract:
assert not diff.has_changes()
# All endpoints should be accounted for
total_changes = (
len(diff.added_endpoints) +
len(diff.removed_endpoints) +
len(diff.modified_endpoints)
)
assert total_changes >= 0
MCP Tool Implementation
case "bridge_sync": {
const dep = (args as any)?.dependency || "";
return this.runBridgeCommand(`sync ${dep}`);
}
private runBridgeCommand(command: string) {
try {
const output = execSync(`specsync-bridge ${command}`, {
encoding: "utf-8",
timeout: 60000,
cwd: process.cwd(),
});
return { content: [{ type: "text", text: output }] };
} catch (error: any) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
}
Parallel Sync with Progress
with ThreadPoolExecutor(max_workers=5) as executor:
future_to_dep = {
executor.submit(self._sync_with_progress, dep): dep
for dep in dependency_names
}
for future in as_completed(future_to_dep):
result = future.result()
results.append(result)
Results
Test Coverage
- 230 tests total (unit, integration, property-based)
- 107 bridge-specific tests (all passing)
- 100+ property-based test iterations per property
Performance
- Contract extraction: < 1s for typical repo
- Sync (first time): 2-5s per dependency
- Sync (cached): < 1s per dependency
- Validation: < 2s for typical codebase
- Parallel sync: O(slowest dependency) not O(sum)
Features Delivered
- ✅ Commit-time validation (spec-code-test-doc)
- ✅ Cross-repo contract sync via git
- ✅ Drift detection (missing endpoints, parameter mismatches)
- ✅ Auto-detection (provider vs. consumer)
- ✅ Offline fallback (cached contracts)
- ✅ Parallel sync (multiple dependencies)
- ✅ Auto-sync (configurable intervals: 30min, 1h, 2h, 3h, 6h)
- ✅ Interactive setup wizard (one-command onboarding)
- ✅ MCP integration (9 tools for Kiro)
- ✅ CLI (
specsync-bridgecommand) - ✅ Pip-installable package (PyPI)
- ✅ NPM-installable MCP server
What's Next
Short Term
- Support for GraphQL and gRPC contracts
- TypeScript/JavaScript endpoint extraction
- Breaking change impact analysis
- Visual dependency graphs
- Webhook support for instant contract updates
Long Term
- Contract versioning and compatibility checking
- Automated migration suggestions
- IDE plugins for inline drift warnings
- Response schema validation (beyond endpoint matching)
- Slack/Discord notifications for breaking changes
Try It Yourself
# Install
pip install specsync-bridge
# Provider repo
specsync-bridge detect # Auto-detect role
specsync-bridge init --role provider
specsync-bridge extract # Extract contract
git add .kiro/contracts/provided-api.yaml
git commit -m "Add API contract"
# Consumer repo
specsync-bridge init --role consumer
specsync-bridge add-dependency backend --git-url <url>
specsync-bridge sync # Fetch contract
specsync-bridge validate # Check for drift
Conclusion
SpecSync proves that drift is preventable. By validating at commit time and syncing contracts across repos, I catch misalignment before it becomes a bug.
The combination of MCP integration (for Kiro orchestration) and git-based sync (for cross-repo contracts) creates a system that's both powerful and practical.
Drift monsters, meet your match. 🐉⚔️
Built With
Languages:
- Python 3.9+ (backend, validation, CLI)
- TypeScript (MCP server)
Frameworks & Libraries:
- FastAPI (example API)
- Model Context Protocol SDK (
@modelcontextprotocol/sdk) - Hypothesis (property-based testing)
- pytest (testing framework)
- PyYAML (contract serialization)
Tools & Platforms:
- Git (contract sync)
- Kiro IDE (MCP client)
- GitHub (version control)
- pip (package distribution)
Key Technologies:
- AST parsing (
astmodule) - Subprocess management (
subprocess,ThreadPoolExecutor) - MCP (Model Context Protocol)
- Property-based testing
- Git hooks (pre-commit validation)
Testing:
- pytest (unit & integration tests)
- Hypothesis (property-based tests)
- 230 total tests, 100% passing
Built With
- ast
- fastapi
- git
- hypothesis
- mcp
- pip
- python
- typescript

Log in or sign up for Devpost to join the conversation.