ЁЯПл The SchoolтА║ЁЯФМ MCPтА║ЁЯПл рдзрдбрд╛ 02 тАФ Architecture: hosts, clients, servers
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯПл рдзрдбрд╛ 02 тАФ Architecture: hosts, clients, servers

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 8 рдкреИрдХреА рдзрдбрд╛ 02 ┬╖ рдорд╛рдЧреЗ: lesson-01-why-mcp ┬╖ рдкреБрдвреЗ: lesson-03-primitives


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбрд╛ 01, рдЖрдгрд┐ рддреАрди рднреВрдорд┐рдХрд╛ рд╡ рдирдХреНрдХреА рдХреЛрдг рдХреЛрдгрд╛рд╢реА рдмреЛрд▓рддреЛ тАФ рдХреЛрдгрддреАрд╣реА wire traffic рд╡рд╛рдЪрдгреНрдпрд╛рдкреВрд░реНрд╡реА рд▓рд╛рдЧрдгрд╛рд░рд╛ рдирдХрд╛рд╢рд╛.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

Socket рд╡реНрдпрд╡рд╕реНрдереЗрддреАрд▓ рддреАрди рднреВрдорд┐рдХрд╛:

рд╕реВрдХреНрд╖реНрдо рдкрдг рдорд╣рддреНрддреНрд╡рд╛рдЪрд╛ рднрд╛рдЧ: model рдХрдзреАрдЪ socket рд▓рд╛ рд╣рд╛рдд рд▓рд╛рд╡рдд рдирд╛рд╣реА. рд╡рд┐рджреНрдпрд╛рд░реНрдерд┐рдиреА рд╢рдмреНрджрд╛рдВрдд рдореНрд╣рдгрддреЗ "рдорд▓рд╛ lookup_grade call рдХрд░рд╛рдпрдЪрд╛ рдЖрд╣реЗ" (рдПрдХ structured tool call тАФ AI рдХреЛрд░реНрд╕ L11); рддреЗ рдЦрд░реЛрдЦрд░ рдХрд░рд╛рдпрдЪреЗ рдХреА рдирд╛рд╣реА рддреЗ рдЦреЛрд▓реА рдард░рд╡рддреЗ, socket message рд╡рд╛рд╣реВрди рдиреЗрддреЗ, рдЙрдкрдХрд░рдг рдЙрддреНрддрд░ рджреЗрддреЗ, рдЖрдгрд┐ result рд╡рд┐рджреНрдпрд╛рд░реНрдерд┐рдиреАрдЪреНрдпрд╛ рдмрд╛рдХрд╛рд╡рд░ рдареЗрд╡рд▓рд╛ рдЬрд╛рддреЛ. Model рд╕реБрдЪрд╡рддреЛ; host рдард░рд╡рддреЛ. рдзрдбрд╛ 05 рдордзреАрд▓ рд╕рдЧрд│реА рд╕реБрд░рдХреНрд╖рд╛ рддреНрдпрд╛рдЪ рдлрдЯреАрдд рд░рд╛рд╣рддреЗ.

рдХреЛрдг рдХрд╛рдп рдард░рд╡рддреЗ тАФ рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рдгреНрдпрд╛рдЪрд╛ рддрдХреНрддрд╛:

рдирд┐рд░реНрдгрдп рдХреЛрдг рдард░рд╡рддреЗ рддреЗ рдХреБрдареЗ рдЕрд╕рддреЗ
рдХреЛрдгрддреА рдЙрдкрдХрд░рдгреЗ рдЬреЛрдбрд▓реА рдЖрд╣реЗрдд user (host рдЪреНрдпрд╛ settings рдордзреВрди) host config / allow-list
рдмрд╛рдХрд╛рд╡рд░ рдХрд╛рдп рдЬрд╛рддреЗ (resources, history) host / app host
рдХреЛрдгрддрд╛ tool, рдХреЛрдгрддреНрдпрд╛ arguments рд╕рд╣ call рдХрд░рд╛рдпрдЪрд╛ model тАФ рд╕реВрдЪрдирд╛ рдореНрд╣рдгреВрди model output
рддреЛ call рдЦрд░реЛрдЦрд░ рдЪрд╛рд▓рддреЛ рдХреА рдирд╛рд╣реА host (policy, permission prompt) host тАФ рд╕рддреНрддреЗрдЪрд╛ рдХреНрд╖рдг (L07)
рдПрдЦрд╛рджреЗ write рд╣реЛрддреЗ рдХреА рдирд╛рд╣реА рдорд╛рдгрд╕рд╛рдЪрд╛ click (рдзреЛрд░рдг 3, L05) host UI
tool рдХрд╛рдп рдХрд░рддреЛ рдЖрдгрд┐ рдХрд╛рдп рдкрд░рдд рджреЗрддреЛ server server code

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    subgraph host["ЁЯПл HOST - e.g. your IDE"]
        model["ЁЯза the model<br/>proposes tool calls in words"]
        c1["ЁЯФМ client #1"]
        c2["ЁЯФМ client #2"]
    end
    s1["ЁЯФм server: filesystem<br/>(local child process)"]
    s2["ЁЯФм server: GitHub<br/>(remote, Streamable HTTP)"]
    model -->|"1 'I want lookup_grade(тАж)'"| c1
    c1 <-->|"2 JSON-RPC"| s1
    c2 <-->|"2 JSON-RPC"| s2
    s1 -->|"3 result тЖТ the desk"| model

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдкреНрд░рддреНрдпреЗрдХ debugging session рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ security рдкреНрд░рд╢реНрди рдпрд╛ рдирдХрд╛рд╢рд╛рддреВрдирдЪ рдЬрд╛рддреЛ: "model рдиреЗ X рдХреЗрд▓реЗ" рдореНрд╣рдгрдЬреЗ рдЬрд╡рд│рдЬрд╡рд│ рдиреЗрд╣рдореА "HOST рдиреЗ X рдХрд░реВ рджрд┐рд▓реЗ". рдЖрдгрд┐ рдПрдЦрд╛рджреНрдпрд╛ рдЕрдиреЛрд│рдЦреА рд╡реНрдпрдХреНрддреАрдиреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓рд╛ server рддреБрдордЪреНрдпрд╛ рдЦреЛрд▓реАрдд тАФ рддреНрдпрд╛рдЪреНрдпрд╛рдмрджреНрджрд▓ рдХрд╛рд╣реАрд╣реА рдорд╛рд╣реАрдд рдирд╕рддрд╛рдирд╛ тАФ рдЪрд╛рд▓рддреЛ, рдпрд╛рдЪреЗ рдХрд╛рд░рдг рднреВрдорд┐рдХрд╛ рдлрдХреНрдд рдорд╛рдирдХ socket рд╡рд░рдЪ рднреЗрдЯрддрд╛рдд. рдЕрд░реБрдВрдж interfaces, рдмрджрд▓рддрд╛ рдпреЗрдгрд╛рд░реЗ рднрд╛рдЧ: рд╣реАрдЪ рд╕рдВрдкреВрд░реНрдг рдпреБрдХреНрддреА.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

python3 client/mini_client.py

рдЖрддрд╛ рдЬреЗ рджрд┐рд╕рддреЗ рддреНрдпрд╛рддреАрд▓ рднреВрдорд┐рдХрд╛ рдУрд│рдЦрд╛: mini_client.py host рдЖрдгрд┐ client рджреЛрдиреНрд╣реА рдмрдирд▓рд╛ рдЖрд╣реЗ (рддреЛ child рд╕реБрд░реВ рдХрд░рддреЛ рдЖрдгрд┐ socket рддреНрдпрд╛рдЪреНрдпрд╛рдХрдбреЗ рдЖрд╣реЗ); school_server.py рд╣реЗ рдЙрдкрдХрд░рдг рдЖрд╣реЗ; рдЖрдгрд┐ рднрд╛рдЧ 3 рдордзреАрд▓ scripted calls model рдЪреНрдпрд╛ рд╕реВрдЪрдиреЗрдЪреА рдЬрд╛рдЧрд╛ рдШреЗрддрд╛рдд. рдордЧ --drive рд╕рд╣ рдЪрд╛рд▓рд╡рд╛ тАФ рдЖрддрд╛ model рддреБрдореНрд╣реА рдЖрд╣рд╛рдд, рдЖрдгрд┐ рд▓рдХреНрд╖рд╛рдд рдШреНрдпрд╛: рддреБрдореНрд╣реА рдлрдХреНрдд рд╕реБрдЪрд╡реВ рд╢рдХрддрд╛; host рдордзреНрдпрд╕реНрдереА рдХрд░рддреЛ рдЖрдгрд┐ рдкреНрд░рддреНрдпрдХреНрд╖ рд╕реНрдкрд░реНрд╢ client рдХрд░рддреЛ.

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

Scripted run рдордзреНрдпреЗ тЖТ рдУрд│реА рдореНрд╣рдгрдЬреЗ client (socket) рдмреЛрд▓рддреЛ рдЖрдгрд┐ тЖР рдУрд│реА рдореНрд╣рдгрдЬреЗ server; model рдЬреЗ рдмреЛрд▓реЗрд▓ рддреЗ wire рд╡рд░ рдХрдзреАрдЪ рджрд┐рд╕рдд рдирд╛рд╣реА. --drive рдордзреНрдпреЗ рддреБрдореНрд╣реА call рд╕рд╛рдареА рд╡рд┐рдирдВрддреА рдЯрд╛рдЗрдк рдХрд░рддрд╛ рдЖрдгрд┐ host рддрд┐рдЪреЗ tools/call рдордзреНрдпреЗ рд░реВрдкрд╛рдВрддрд░ рдХрд░рддреЛ.

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

рддреАрди рднреВрдорд┐рдХрд╛ code рдордзреНрдпреЗ рд╡реЗрдЧрд│реНрдпрд╛ рдХрд░рддрд╛ рдпреЗрддрд╛рдд: MiniHost (рдЦреЛрд▓реА + socket) рдЖрдгрд┐ school_server.py (рдЙрдкрдХрд░рдг) рдлрдХреНрдд wire рд╡рд░ рднреЗрдЯрддрд╛рдд; model рдХрдзреАрдЪ socket рд▓рд╛ рд╣рд╛рдд рд▓рд╛рд╡рдд рдирд╛рд╣реА.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: "рдХреЛрдг рдХрд╛рдп рдард░рд╡рддреЗ" рд╣реАрдЪ рддреБрдордЪреА security architecture рдЖрд╣реЗ. Permission prompts, allow-lists рдЖрдгрд┐ logs host рдордзреНрдпреЗ рдареЗрд╡рд╛, рдХрд╛рд░рдг model рдЪреА рд╕реВрдЪрдирд╛ рдЖрдгрд┐ user рджреЛрдиреНрд╣реА рдкрд╛рд╣рдгрд╛рд░реА рддреА рдПрдХрдореЗрд╡ рдЬрд╛рдЧрд╛ рдЖрд╣реЗ.

тПня╕П рдкреБрдвреЗ

рдЙрдкрдХрд░рдг рдирдХреНрдХреА рдХрд╛рдп рджреЗрдК рд╢рдХрддреЗ? рддреАрди рдХрдкреНрдкреЗ: tools, resources, prompts.

git checkout lesson-03-primitives

ЁЯПл Lesson 02 тАФ The architecture: hosts, clients, servers

ЁЯУН You are here: Lesson 02 of 8 ┬╖ Previous: lesson-01-why-mcp ┬╖ Next: lesson-03-primitives


ЁЯУж What's in this branch

Lesson 01, plus the three roles and exactly who talks to whom тАФ the map you need before reading any wire traffic.

ЁЯзТ Explain like I'm 5

Three roles in the socket system:

The subtle, important bit: the model never touches the socket. The student says "I want to call lookup_grade" in words (a structured tool call тАФ AI course L11); the ROOM decides whether to actually do it, the socket carries the message, the instrument answers, and the result is placed on the student's desk. Model proposes; host disposes. That gap is where all of lesson 05's safety lives.

Who decides what тАФ the table to keep:

Decision Who decides Where it lives
which instruments are plugged in the user (via the host's settings) host config / allow-list
what goes on the desk (resources, history) the host / app host
which tool to call, with which arguments the model тАФ as a proposal model output
whether that call actually runs the host (policy, permission prompt) host тАФ the power moment (L07)
whether a write happens a human click (policy 3, L05) host UI
what the tool does and returns the server server code

ЁЯЧ║я╕П Diagram

flowchart LR
    subgraph host["ЁЯПл HOST - e.g. your IDE"]
        model["ЁЯза the model<br/>proposes tool calls in words"]
        c1["ЁЯФМ client #1"]
        c2["ЁЯФМ client #2"]
    end
    s1["ЁЯФм server: filesystem<br/>(local child process)"]
    s2["ЁЯФм server: GitHub<br/>(remote, Streamable HTTP)"]
    model -->|"1 'I want lookup_grade(тАж)'"| c1
    c1 <-->|"2 JSON-RPC"| s1
    c2 <-->|"2 JSON-RPC"| s2
    s1 -->|"3 result тЖТ the desk"| model

тЭУ What

ЁЯдФ Why

Every debugging session and every security question routes through this map: "the model did X" is almost always "the HOST allowed X". And the reason a server written by a stranger works in your room тАФ without knowing anything about it тАФ is that the roles only meet at the standard socket. Narrow interfaces, swappable parts: the whole trick.

ЁЯзк Try it

python3 client/mini_client.py

Now name the roles in what you see: mini_client.py is playing host AND client (it launches the child and owns the socket); school_server.py is the instrument; and in part 3, the scripted calls stand in for the model proposing. Then run with --drive тАФ now YOU are the model, and notice: you can only propose; the host mediates and the client does the touching.

тЬЕ Verify тАФ what you should see

In the scripted run, тЖТ lines are the client (socket) speaking and тЖР lines the server; nothing the model would say ever appears on the wire. In --drive you type a request for a call and the host turns it into tools/call.

ЁЯПБ What you just proved

The three roles are separable in code: MiniHost (room + socket) and school_server.py (instrument) meet only at the wire; the model never touches the socket.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: "who decides what" is your security architecture. Put permission prompts, allow-lists and logs in the host, because that is the only place that sees both the model's proposal and the user.

тПня╕П Next

What exactly can an instrument offer? The three shelves: tools, resources, prompts.

git checkout lesson-03-primitives
тЖР Previouswhy mcpNext тЖТprimitives

This page is the lesson's README from the lesson-02-architecture branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.