AI rules and MCP help even without Uclusion

AI rules and MCP help even without Uclusion

Part of Uclusion’s AI collaboration isn’t really about Uclusion at all. It comes down to two pieces you can build for almost any system:

  1. A rules file that turns a coding agent into a disciplined collaborator instead of an eager intern that runs off and does the wrong thing.
  2. An MCP server (and a tiny proxy for auth) so the agent can actually read and write the system you care about.

Here is how to wire the same flow into whatever you already use.

A rules file is the workflow

Our public CLAUDE.md is a plain markdown file that pins the agent to an ordered workflow:

  1. Read the whole job before touching anything.
  2. Ask questions about anything ambiguous, before deciding.
  3. Make suggestions when it sees a better path, instead of silently going its own way.
  4. Approve with a recorded certainty once questions are answered.
  5. Execute and document decisions as it goes.
  6. Ask for review when there is a testable result.

Two rules do most of the work. First, questions come before decisions — any judgment call a reasonable reviewer might make differently is a question, not a silent guess. Second, every artifact lives in the system, not in chat — questions, suggestions, approvals, and progress notes are written back through tools so the next session (yours or the agent’s) can pick up the thread.

This can be a template. Point the rules at your own MCP tools, rename the steps, drop the ones you do not need. You do not even need an MCP server to start — you can write the rules to say “at this step, paste the ticket here” or “stop and show me the diff” and run the whole flow by hand in the AI console. The discipline is in the file, not in the integration.

Your own MCP server is not hard

Once the rules reference tools, you need an MCP server behind them. There is less here than people expect. MCP is JSON-RPC, and a server really only has to answer three methods: initialize, tools/list, and tools/call. Everything else is your own business logic.

Here is the shape of our request validator — reject anything that is not a known method or a known tool:

from mcp.types import JSONRPCRequest
from ucommon.validators.abstract_request_validator import AbstractRequestValidator
from ucommon.validators.business_logic_exception import BusinessLogicException

class MCPServeValidator(AbstractRequestValidator):
    def validate_business_logic(self, user_id, data, event):
        if data.get('method') in ['notifications/initialized', 'notifications/cancelled', 'ping']:
            return {}
        # Validate the incoming request with the official SDK model
        request = JSONRPCRequest.model_validate(data)
        if request.method not in ("initialize", "tools/list", "tools/call"):
            raise BusinessLogicException(f"Method not found: {request.method}", 404)
        tool_name = None
        if request.method == "tools/call":
            tool_name = request.params.get("name")
            if tool_name not in ("get_job", "ask_question", "make_suggestion",
                                 "approve_job_or_option", "add_info", "resolve", "ask_for_review"):
                raise BusinessLogicException(f"Unknown tool: {tool_name}", 404)
        return {'request': request, 'tool_name': tool_name}

Then route the three methods and serialize a response. Note that Uclusion’s MCP server runs as an AWS Lambda so using the full FastMCP server launching its own instance was too heavy.

def post_validation_function(event, data, context, validation_context):
    request = validation_context['request']
    if request.method == "initialize":
        result_data = handle_initialize()
    elif request.method == "tools/list":
        result_data = handle_list_tools()
    elif request.method == "tools/call":
        result_data = handle_call_tool(request.params, validation_context['tool_name'])
    response = JSONRPCResponse(jsonrpc="2.0", id=request.id, result=result_data)
    return response.model_dump(by_alias=True, exclude_none=True)

def handle_initialize():
    return InitializeResult(
        protocolVersion="2024-11-05",
        capabilities={"tools": {}},
        serverInfo={"name": "your-mcp-server", "version": "1.0.0"},
    ).model_dump(by_alias=True, exclude_none=True)

handle_list_tools just returns one Tool entry per verb you expose. A tiny mock for some other system might look like:

def handle_list_tools():
    return ListToolsResult(tools=[
        Tool(
            name="get_ticket",
            description="Fetch a ticket and its comments by id.",
            inputSchema={
                "type": "object",
                "properties": {"ticket_id": {"type": "string"}},
                "required": ["ticket_id"],
            },
        ),
        Tool(
            name="add_comment",
            description="Add a comment to a ticket.",
            inputSchema={
                "type": "object",
                "properties": {
                    "ticket_id": {"type": "string"},
                    "body": {"type": "string"},
                },
                "required": ["ticket_id", "body"],
            },
        ),
    ]).model_dump(by_alias=True, exclude_none=True)

handle_call_tool then dispatches each name to your real code. That is the whole server — swap these stand-ins for whatever verbs your system needs.

Custom auth with a tiny proxy

The last piece is getting an agent on a developer’s laptop authenticated as a machine user against your backend. That is what our uclusionMCPProxy.py does, in about 150 lines.

It is intentionally boring: read credentials from a file under ~/.uclusion, log in to get a token, then sit in a loop reading JSON-RPC off stdin and POSTing it to the MCP endpoint with the token attached — handling both plain JSON and SSE responses and keeping the session id between calls. The agent speaks vanilla MCP over stdio; the proxy is the only thing that knows how to authenticate into your world.

This is the seam to copy. If your system has its own SSO, API keys, or a machine-user concept, you only have to change get_credentials() and login(). Everything downstream — the agent, the rules file, the tool definitions — stays the same.

Where Uclusion beats DIY

None of the above requires Uclusion. What Uclusion adds is a rich UI where questions, options, approvals, and reviews are first-class objects. The rules file keeps the agent honest; Uclusion is where you, the agent, and potentially teammates actually meet.

If you want to see that side of it, signing up is free.

David Israel
David Israel Co-Founder of Uclusion