FRAMEWORK DESIGNINTERMEDIATE

Build Your First MCP Server with TypeScript: Step-by-Step Guide for SDETs and Playwright Engineers

Build your first Model Context Protocol MCP server with TypeScript step by step. Learn how to create MCP Tools, Resources and Prompts, connect an MCP client using stdio, and understand how MCP servers prepare SDETs for Playwright MCP and Agentic AI testing.

iff Solution Academy September 12, 2026 30 min read Updated September 12, 2026
MCP MCP Server TypeScript MCP Tools Playwright MCP AI Agents Agentic AI SDET

In the previous tutorials, we learned the theory behind MCP: MCP Fundamentals (tutorial 1), the MCP Host, Client & Server architecture (tutorial 2), and MCP Tools, Resources & Prompts (tutorial 3). Now it is time to actually build one.

text
Tutorial 1
MCP Fundamentals
        ↓
Tutorial 2
MCP Host, Client & Server
        ↓
Tutorial 3
MCP Tools, Resources & Prompts
        ↓
Tutorial 4
BUILD YOUR FIRST MCP SERVER

Instead of only discussing Host, Client, Server, Tools, Resources and Prompts, we will create a working MCP server using TypeScript. Our server will expose 1 Tool, 1 Resource and 1 Prompt. Then we will build a small MCP client and connect it to the server.

text
MCP CLIENT
     │
     │ MCP
     ▼
QA MCP SERVER
     │
     ├── TOOL
     │
     ├── RESOURCE
     │
     └── PROMPT

This is the foundation you need before moving into Playwright MCP, GitHub Copilot + MCP, Testing Agents and Agentic AI Testing.

1. What Are We Building?

We will create a small MCP server called qa-mcp-server. It will expose three capabilities.

  • Tool: validate-product-price — validates whether a product price is valid according to a simple business rule.
  • Resource: qa://testing-guidelines — provides QA testing guidelines to the MCP client.
  • Prompt: review-requirement — a reusable prompt for analyzing software requirements.
text
                     QA MCP SERVER
                           │
          ┌────────────────┼────────────────┐
          │                │                │
          ▼                ▼                ▼
        TOOL            RESOURCE          PROMPT
 Validate Product     QA Guidelines     Requirement
      Price                                Review

2. Prerequisites

For the current TypeScript SDK, use Node.js 20+, npm, TypeScript and VS Code. The MCP TypeScript documentation currently recommends Node.js 20 or later for the getting-started flow.

bash
node --version
# v20.x.x or newer

npm --version

3. Create the Project

bash
mkdir qa-mcp-server
cd qa-mcp-server

# Initialize Node
npm init -y

# Enable ES modules
npm pkg set type=module
text
qa-mcp-server/
│
└── package.json

4. Install MCP Server Dependencies

bash
npm install @modelcontextprotocol/server zod tsx

mkdir src

The current v2 SDK publishes the server separately as @modelcontextprotocol/server; Zod can be used to define input schemas.

text
qa-mcp-server/
│
├── node_modules/
│
├── src/
│
├── package.json
└── package-lock.json

5. Why Do We Need Zod?

MCP tools and prompts can define structured inputs. For example, our tool needs a price value that should be a number. We can define it using Zod:

typescript
z.object({
  price: z.number()
})

The MCP SDK validates tool calls against the schema before invoking the handler. This helps prevent invalid input from reaching our business logic.

6. Create the MCP Server

Create src/index.ts and start with the imports:

typescript
import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
import * as z from 'zod/v4';
text
McpServer
     ↓
Creates our MCP server

serveStdio
     ↓
Connects the server using stdio

Zod
     ↓
Defines input schemas

7. Create the Server Instance

typescript
const server = new McpServer({
  name: 'qa-mcp-server',
  version: '1.0.0'
});

Now we have a QA MCP SERVER, but it currently exposes nothing. No tools, no resources, no prompts. Let's add them.

8. Create Our First MCP Tool

We will create validate-product-price. Our business rule is: product price must be greater than 0.

typescript
server.registerTool(
  'validate-product-price',
  {
    title: 'Validate Product Price',
    description:
      'Validates whether a product price is greater than zero.',
    inputSchema: z.object({
      price: z.number()
    })
  },
  async ({ price }) => {

    const valid = price > 0;

    return {
      content: [
        {
          type: 'text',
          text: valid
            ? `PASS: Product price ${price} is valid.`
            : `FAIL: Product price ${price} must be greater than zero.`
        }
      ]
    };
  }
);

Current SDK v2 uses registerTool(name, config, handler) and schema objects such as z.object(...).

9. Understand the Tool Code

The tool name 'validate-product-price' identifies the tool. The description is very important — the AI may use tool metadata to understand what the tool does and when to use it. Good descriptions improve tool selection.

10. Tool Input Schema

typescript
inputSchema: z.object({
  price: z.number()
})

price = 100 is valid, price = -25 is still technically a number (our business logic determines it is invalid), but price = "hello" would not match the schema at all.

11. Tool Handler

The handler receives the validated input. Our business rule is price > 0. If price = 100 the result is PASS; if price = -5 the result is FAIL.

typescript
async ({ price }) => {
  const valid = price > 0;
  // ...
}

12. Tool Response

text
MCP TOOL
   │
   ▼
EXECUTE LOGIC
   │
   ▼
RESULT
   │
   ▼
MCP CLIENT

13. Tool Execution Architecture

text
MCP CLIENT
     │
     │ Call Tool
     ▼
QA MCP SERVER
     │
     ▼
validate-product-price
     │
     ▼
Check:
price > 0 ?
     │
 ┌───┴───┐
 │       │
YES      NO
 │       │
PASS     FAIL

14. Add Our First MCP Resource

Now we will expose testing information through the resource qa://testing-guidelines.

typescript
server.registerResource(
  'testing-guidelines',
  'qa://testing-guidelines',
  {
    title: 'QA Testing Guidelines',
    description: 'Basic enterprise QA testing guidelines.',
    mimeType: 'text/plain'
  },
  async (uri) => ({
    contents: [
      {
        uri: uri.href,
        text: `
Enterprise QA Testing Guidelines

1. Understand requirements before automation.
2. Review acceptance criteria.
3. Identify positive and negative scenarios.
4. Validate UI and API behavior.
5. Validate backend data when required.
6. Keep tests independent.
7. Avoid shared test data.
8. Use stable selectors.
9. Separate test logic from framework utilities.
10. Run critical tests in CI/CD.
        `.trim()
      }
    ]
  })
);

The current SDK supports registerResource with a URI and a read callback; the handler returns a contents collection.

15. What Did We Just Build?

text
MCP CLIENT
     │
     │ Read Resource
     ▼
QA MCP SERVER
     │
     ▼
qa://testing-guidelines
     │
     ▼
Testing Guidelines
Unlike our tool, the resource is primarily providing information. Remember: TOOL = Action. RESOURCE = Context.

16. Why Resources Matter for SDETs

Imagine a real enterprise MCP server exposing qa://architecture, qa://acceptance-criteria, qa://api-contract, qa://database-schema and qa://automation-standards. An AI agent could retrieve this context before performing testing tasks:

text
Read Requirements
       ↓
Read Test Guidelines
       ↓
Understand Architecture
       ↓
Design Tests
       ↓
Execute Tests

17. Add Our First MCP Prompt

typescript
server.registerPrompt(
  'review-requirement',
  {
    title: 'Review Software Requirement',
    description:
      'Reviews a software requirement from an SDET perspective.',
    argsSchema: z.object({
      requirement: z.string()
    })
  },
  ({ requirement }) => ({
    messages: [
      {
        role: 'user',
        content: {
          type: 'text',
          text: `
Review the following software requirement:

${requirement}

Analyze it from an SDET perspective.

Identify:

1. Functional requirements
2. Business rules
3. Positive test scenarios
4. Negative test scenarios
5. Boundary conditions
6. Missing information
7. API testing needs
8. Database validation needs
9. Security considerations
10. Automation opportunities
          `.trim()
        }
      }
    ]
  })
);

The v2 SDK provides registerPrompt(name, config, callback) and supports an argsSchema such as a Zod object.

18. Understand the Prompt

The prompt accepts a requirement, for example: "An administrator should be able to create a product. Product name is mandatory. Price must be greater than zero." The reusable prompt then asks the AI to analyze functional requirements, business rules, positive/negative scenarios, boundary cases, missing requirements, API testing, database testing, security and automation opportunities. Instead of rewriting these instructions every time, we package them into a reusable MCP prompt.

19. Our MCP Server Now Has All Three

text
                     QA MCP SERVER
                           │
           ┌───────────────┼───────────────┐
           │               │               │
           ▼               ▼               ▼
         TOOL           RESOURCE          PROMPT
validate-product-      testing-          review-
     price             guidelines       requirement
text
TOOL
=
DO SOMETHING

RESOURCE
=
PROVIDE INFORMATION

PROMPT
=
PROVIDE REUSABLE INSTRUCTIONS

20. Start the MCP Server Using stdio

Now we need a transport. For our local tutorial we will use stdio. The easiest complete structure wraps the server creation:

typescript
import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
import * as z from 'zod/v4';

serveStdio(() => {

  const server = new McpServer({
    name: 'qa-mcp-server',
    version: '1.0.0'
  });

  // register capabilities here

  return server;
});

The official SDK supports stdio for local, process-spawned MCP integrations.

21. Complete MCP Server Code

Your complete src/index.ts can look like this:

typescript
import { McpServer } from '@modelcontextprotocol/server';
import { serveStdio } from '@modelcontextprotocol/server/stdio';
import * as z from 'zod/v4';

serveStdio(() => {

  const server = new McpServer({
    name: 'qa-mcp-server',
    version: '1.0.0'
  });

  // =====================================================
  // TOOL
  // =====================================================

  server.registerTool(
    'validate-product-price',
    {
      title: 'Validate Product Price',
      description:
        'Validates whether a product price is greater than zero.',
      inputSchema: z.object({
        price: z.number()
      })
    },

    async ({ price }) => {

      const valid = price > 0;

      return {
        content: [
          {
            type: 'text',
            text: valid
              ? `PASS: Product price ${price} is valid.`
              : `FAIL: Product price ${price} must be greater than zero.`
          }
        ]
      };
    }
  );

  // =====================================================
  // RESOURCE
  // =====================================================

  server.registerResource(
    'testing-guidelines',
    'qa://testing-guidelines',
    {
      title: 'QA Testing Guidelines',
      description:
        'Basic enterprise QA testing guidelines.',
      mimeType: 'text/plain'
    },

    async (uri) => ({
      contents: [
        {
          uri: uri.href,
          text: `
Enterprise QA Testing Guidelines

1. Understand requirements before automation.
2. Review acceptance criteria.
3. Identify positive and negative scenarios.
4. Validate UI and API behavior.
5. Validate backend data when required.
6. Keep tests independent.
7. Avoid shared test data.
8. Use stable selectors.
9. Separate test logic from framework utilities.
10. Run critical tests in CI/CD.
          `.trim()
        }
      ]
    })
  );

  // =====================================================
  // PROMPT
  // =====================================================

  server.registerPrompt(
    'review-requirement',
    {
      title: 'Review Software Requirement',
      description:
        'Reviews a software requirement from an SDET perspective.',

      argsSchema: z.object({
        requirement: z.string()
      })
    },

    ({ requirement }) => ({
      messages: [
        {
          role: 'user',
          content: {
            type: 'text',
            text: `
Review the following software requirement:

${requirement}

Analyze it from an SDET perspective.

Identify:

1. Functional requirements
2. Business rules
3. Positive test scenarios
4. Negative test scenarios
5. Boundary conditions
6. Missing information
7. API testing needs
8. Database validation needs
9. Security considerations
10. Automation opportunities
            `.trim()
          }
        }
      ]
    })
  );

  return server;
});

22. Project Structure

text
qa-mcp-server/
│
├── src/
│   └── index.ts
│
├── package.json
├── package-lock.json
└── node_modules/

23. Add a Start Script

json
{
  "scripts": {
    "start": "tsx src/index.ts"
  }
}
bash
npm start

You may not see a normal web application screen. That is expected. This is not a React application or a REST API UI — it is an MCP server waiting for MCP communication.

24. Why Don't We Open localhost:3000?

This is an important concept. Our server currently uses stdio, not an HTTP web server.

text
MCP CLIENT
     │
     │ stdin / stdout
     ▼
MCP SERVER

You therefore do not test this local stdio server by simply opening http://localhost:3000. A compatible MCP client communicates with it through the configured transport.

25. What Is stdio?

text
CLIENT
  │
  │ request
  ▼
stdin

MCP SERVER

stdout
  │
  │ response
  ▼
CLIENT

stdio means Standard Input + Standard Output. This is particularly useful for local MCP servers that a host launches as a child process.

26. Build a Small MCP Client

To fully understand what is happening, let's create our own client. The v2 TypeScript SDK provides the client as a separate package.

bash
npm install @modelcontextprotocol/client

Create src/client.ts.

27. Connect the Client to Our Server

typescript
import { Client } from '@modelcontextprotocol/client';

import {
  StdioClientTransport
} from '@modelcontextprotocol/client/stdio';

const client = new Client({
  name: 'qa-mcp-client',
  version: '1.0.0'
});

const transport = new StdioClientTransport({
  command: 'npx',
  args: ['tsx', 'src/index.ts']
});

await client.connect(transport);

When connect() is called, the stdio client transport can launch the MCP server as a child process and complete the MCP initialization handshake.

text
client.ts
   │
   ▼
MCP Client
   │
   │ launches
   ▼
index.ts
   │
   ▼
MCP Server

28. List Available Tools

typescript
const tools = await client.listTools();

console.log('TOOLS');

console.log(
  tools.tools.map(tool => tool.name)
);
text
TOOLS

[
  'validate-product-price'
]

The client has discovered the tool exposed by our server.

29. Call the Tool

typescript
const toolResult = await client.callTool({
  name: 'validate-product-price',
  arguments: {
    price: 100
  }
});

console.log('TOOL RESULT');
console.log(toolResult);
text
Client
   ↓
validate-product-price
   ↓
price = 100
   ↓
price > 0
   ↓
PASS

Try price: -100. Now -100 > 0 is FALSE, so the result is FAIL.

30. Read the Resource

typescript
const resources = await client.listResources();

console.log('RESOURCES');
console.log(
  resources.resources.map(resource => resource.uri)
);
// [ 'qa://testing-guidelines' ]

const resource = await client.readResource({
  uri: 'qa://testing-guidelines'
});

console.log('RESOURCE');
console.log(resource.contents);

The client receives our testing guidelines.

31. The Resource Flow

text
CLIENT
   │
   │ resources/read
   ▼
MCP SERVER
   │
   ▼
qa://testing-guidelines
   │
   ▼
QA Guidelines
   │
   ▼
CLIENT

The current SDK distinguishes reading resources by URI from calling executable tools.

32. Discover the Prompt

text
CLIENT
   ↓
List Prompts
   ↓
SERVER
   ↓
review-requirement

The client can retrieve the reusable prompt and supply its required argument: requirement. For example: "Admin users can create products. Product name is required. Price must be greater than zero." The returned prompt becomes structured context that an AI host can provide to its model.

33. Important Point: The MCP Server Is Not the LLM

Our server contains the prompt "Review this requirement...", but our server itself is not performing AI reasoning.

text
MCP SERVER
     │
     │ returns prompt
     ▼
MCP HOST
     │
     ▼
LLM
     │
     ▼
AI RESPONSE
MCP server: provides the prompt. LLM: performs the reasoning. This is one of the most important distinctions in MCP.

34. Close the Client

typescript
await client.close();

This ends the connection. For production-quality client code, use finally so the connection closes even if something fails. The official client guide recommends this pattern to avoid leaving spawned server processes running.

35. Complete Client Example

typescript
import { Client } from '@modelcontextprotocol/client';

import {
  StdioClientTransport
} from '@modelcontextprotocol/client/stdio';

const client = new Client({
  name: 'qa-mcp-client',
  version: '1.0.0'
});

const transport = new StdioClientTransport({
  command: 'npx',
  args: ['tsx', 'src/index.ts']
});

try {

  await client.connect(transport);

  console.log('\nCONNECTED TO MCP SERVER\n');

  // ========================================
  // LIST TOOLS
  // ========================================

  const tools = await client.listTools();

  console.log('TOOLS');
  console.log(
    tools.tools.map(tool => tool.name)
  );

  // ========================================
  // CALL TOOL
  // ========================================

  const toolResult = await client.callTool({
    name: 'validate-product-price',
    arguments: {
      price: 100
    }
  });

  console.log('\nTOOL RESULT');
  console.log(toolResult);

  // ========================================
  // LIST RESOURCES
  // ========================================

  const resources =
    await client.listResources();

  console.log('\nRESOURCES');
  console.log(
    resources.resources.map(
      resource => resource.uri
    )
  );

  // ========================================
  // READ RESOURCE
  // ========================================

  const resource =
    await client.readResource({
      uri: 'qa://testing-guidelines'
    });

  console.log('\nRESOURCE CONTENT');
  console.log(resource.contents);

} finally {

  await client.close();

}

36. Run the Client

bash
npx tsx src/client.ts
text
The client:

Starts
  ↓
Launches MCP Server
  ↓
Initializes Connection
  ↓
Discovers Tool
  ↓
Calls Tool
  ↓
Discovers Resource
  ↓
Reads Resource
  ↓
Closes Connection

This is your first real MCP client/server interaction.

37. What Actually Happened?

text
src/client.ts
     │
     ▼
MCP CLIENT
     │
     │ stdio
     ▼
src/index.ts
     │
     ▼
MCP SERVER
     │
     ├── Tool
     │
     ├── Resource
     │
     └── Prompt

The client didn't import our functions directly. Instead, it communicated with the server through MCP. That distinction is extremely important.

38. Why Not Just Import a JavaScript Function?

You might ask: why create MCP Client → MCP Server when we could just write validateProductPrice(100)? Because MCP solves a different problem. A regular function is primarily application code. MCP provides a standardized interface through which compatible AI applications can discover and interact with capabilities.

text
Instead of:

Application A
   ↓
Custom Integration

Application B
   ↓
Different Custom Integration

Application C
   ↓
Another Integration

you expose capabilities through:

MCP SERVER

and compatible hosts can understand the protocol.

39. Where Does an AI Host Fit?

Our custom client helped us understand the protocol. A real AI-enabled workflow adds another layer:

text
USER
 │
 ▼
AI HOST
 │
 ▼
AI MODEL
 │
 ▼
MCP CLIENT
 │
 ▼
QA MCP SERVER
 │
 ├── Tools
 ├── Resources
 └── Prompts

Now the model can potentially decide: I need this resource. I should call this tool. This prompt is relevant.

40. How Tool Discovery Helps the AI

Suppose our server describes the tool validate-product-price as "Validates whether a product price is greater than zero." Then the user asks: "Is a product price of -50 valid?" The AI can see an appropriate capability and invoke it.

text
USER QUESTION
      │
      ▼
AI
      │
      ▼
DISCOVER TOOLS
      │
      ▼
validate-product-price
      │
      ▼
CALL TOOL
      │
      ▼
RESULT

41. From Demo Server to Real QA Server

Our example is intentionally simple. A real Quality Engineering MCP server could expose:

text
TOOLS
──────────────────────────
get-test-result
run-api-test
query-qa-database
get-product-by-id
validate-api-schema
check-environment-health
create-test-data
delete-test-data
text
RESOURCES
──────────────────────────
qa://architecture
qa://test-strategy
qa://api-contract
qa://database-schema
qa://coding-standards
qa://environment-guide
text
PROMPTS
──────────────────────────
review-requirement
generate-test-scenarios
analyze-test-failure
review-playwright-test
generate-defect-report

Now MCP starts becoming extremely relevant to SDETs.

42. Example Real QA MCP Architecture

text
                        AI AGENT
                           │
                           ▼
                       MCP CLIENT
                           │
                           ▼
                    QA MCP SERVER
                           │
       ┌───────────────────┼───────────────────┐
       │                   │                   │
       ▼                   ▼                   ▼
     TOOLS              RESOURCES            PROMPTS
 Run API Test        API Contract       Review Requirement
 Query DB            DB Schema          Generate Tests
 Validate JSON       Architecture       Analyze Failure
 Create Test Data    Test Strategy      Defect Summary

43. What If We Add Playwright?

Now it becomes much more interesting. Imagine our MCP tool open-application internally uses Playwright:

text
AI
 │
 ▼
MCP CLIENT
 │
 ▼
QA MCP SERVER
 │
 ▼
Browser Tool
 │
 ▼
PLAYWRIGHT
 │
 ▼
BROWSER
 │
 ▼
APPLICATION

We are now moving toward Playwright MCP.

44. Example Browser Tool Concept

Conceptually, our MCP server could expose navigate, click, type, inspect and snapshot. Then:

text
User

"Verify that login works."

       ↓
AI
       ↓
navigate
       ↓
inspect
       ↓
type username
       ↓
type password
       ↓
click login
       ↓
inspect result

This begins the transition from a simple MCP server into browser-based Agentic Testing.

45. MCP Server vs Playwright Framework

text
Traditional Playwright:

TEST CODE
   │
   ▼
PLAYWRIGHT
   │
   ▼
BROWSER

MCP-connected browser workflow:

AI
 │
 ▼
MCP CLIENT
 │
 ▼
MCP SERVER
 │
 ▼
PLAYWRIGHT
 │
 ▼
BROWSER

Do not confuse these architectures. Both can exist together.

46. Deterministic Automation Still Matters

Traditional Playwright tests remain extremely valuable:

typescript
test('admin creates product', async ({ page }) => {

  await page.goto('/products');

  await page
    .getByRole('button', {
      name: 'Add Product'
    })
    .click();

  await page
    .getByLabel('Product Name')
    .fill('Laptop');

  await page
    .getByLabel('Price')
    .fill('1000');

  await page
    .getByRole('button', {
      name: 'Save'
    })
    .click();

  await expect(
    page.getByText('Laptop')
  ).toBeVisible();

});

This is predictable, repeatable and CI/CD friendly.

47. MCP Adds Another Capability Layer

MCP can enable AI-driven workflows such as exploring an application, understanding an unfamiliar page, investigating a failure, reading engineering context, dynamically selecting tools and coordinating multiple systems.

The goal should not be "MCP replaces Playwright tests." A stronger architecture is: Traditional Automation + MCP Tool Connectivity + AI Reasoning.

48. Local vs Remote MCP Server

text
Our server is local:

CLIENT
   │
   │ stdio
   ▼
LOCAL MCP SERVER

But MCP servers can also use network transports:

AI HOST
   │
   ▼
MCP CLIENT
   │
   │ HTTP
   ▼
REMOTE MCP SERVER
   │
   ▼
ENTERPRISE SYSTEM

For remote servers, security becomes even more important. The current TypeScript SDK supports stdio for local integrations and Streamable HTTP for remote server scenarios.

49. Security Considerations

Our demo tool is harmless: validate a product price. But imagine tools like delete-user, drop-table, deploy-production or delete-cloud-resource. Those capabilities can be dangerous. A production MCP server should consider:

  • Authentication
  • Authorization
  • Least privilege
  • Input validation
  • Environment restrictions
  • Audit logging
  • Secret management
  • Human approval
  • Tool-specific permissions

50. Good Tool Design

Avoid overly generic tools. Bad: executeAnything. Better: queryQaDatabaseReadOnly. Even better for some use cases: getProductById.

Specific tools are often easier to understand, easier to secure, easier to audit, and easier for AI to select correctly.

51. Never Give Testing Agents Unlimited Production Access

text
Bad:

AI AGENT
   │
   ▼
MCP SERVER
   │
   ▼
PRODUCTION DATABASE
FULL ADMIN ACCESS

Better:

AI AGENT
   │
   ▼
QA MCP SERVER
   │
   ▼
QA DATABASE
READ ONLY
Always apply LEAST PRIVILEGE.

52. What We Learned From the Code

We can now map our implementation directly back to the theory:

  • new McpServer(...) — create the server
  • server.registerTool(...) — expose an executable capability
  • server.registerResource(...) — expose information/context
  • server.registerPrompt(...) — expose reusable instructions
  • serveStdio(...) — provide MCP communication through standard input/output
  • new Client(...) — create an MCP client
  • client.connect(...) — connect client and server and perform initialization

53. Full Architecture We Just Built

text
                         USER
                           │
                           ▼
                    MCP CLIENT APP
                           │
                         stdio
                           │
                           ▼
                    QA MCP SERVER
                           │
          ┌────────────────┼────────────────┐
          │                │                │
          ▼                ▼                ▼
validate-product-      testing-          review-
     price             guidelines       requirement
      TOOL              RESOURCE          PROMPT
text
Add an AI host:

                         USER
                           │
                           ▼
                        AI HOST
                           │
                           ▼
                         MODEL
                           │
                           ▼
                      MCP CLIENT
                           │
                           ▼
                      MCP SERVER
                           │
          ┌────────────────┼────────────────┐
          ▼                ▼                ▼
        Tools           Resources         Prompts

That is MCP in practice.

54. Common Beginner Mistakes

  • Mistake 1 — Thinking MCP Server = LLM. Wrong. The MCP server exposes capabilities; the LLM performs reasoning.
  • Mistake 2 — Thinking Tool = Prompt. Wrong. Tool = Action; Prompt = Instruction.
  • Mistake 3 — Thinking Resource = Tool. Wrong. Resource = Information; Tool = Action.
  • Mistake 4 — Giving tools extremely broad permissions, like execute_any_shell_command. Be very careful with generic high-powered tools.
  • Mistake 5 — Putting credentials directly into code. Use environment variables, secret stores, CI secrets or enterprise credential systems instead.

55. Interview Question: What is an MCP Server?

An MCP server is a program or service that exposes capabilities such as tools, resources, and prompts to MCP clients through the Model Context Protocol. The server can act as an adapter between an AI application and external systems such as browsers, databases, APIs, GitHub, Jira, or internal enterprise services.

56. Interview Question: How do you build an MCP server?

text
1. Create project
2. Install MCP SDK
3. Create McpServer
4. Register tools
5. Register resources
6. Register prompts
7. Select transport
8. Start server
9. Connect an MCP client
10. Discover and invoke capabilities

57. Interview Question: What does stdio do?

stdio provides a transport mechanism where an MCP client and a locally spawned MCP server communicate through standard input and standard output.

58. Interview Question: Does an MCP server need all three: tools, resources, and prompts?

No. A server can expose whatever capabilities are appropriate. For example, a Browser MCP Server would expose mostly Tools, while another server might primarily expose documentation as Resources.

59. Interview Question: Why use schemas for tools?

Schemas describe expected inputs, for example z.object({ productId: z.number() }). They improve validation, reliability, tool discoverability and error handling.

60. What We Built vs What Comes Next

text
Our current server:

AI
 ↓
MCP
 ↓
Simple QA Functions

Next we want:

AI
 ↓
MCP
 ↓
PLAYWRIGHT
 ↓
BROWSER
 ↓
APPLICATION

That is where MCP becomes directly connected to your Playwright automation expertise.

61. Learning Progress So Far

text
MCP Fundamentals
        ✓

Host / Client / Server
        ✓

Tools / Resources / Prompts
        ✓

Build MCP Server
        ✓

Next:

PLAYWRIGHT MCP

62. Final Takeaway

The most important lesson from this tutorial is that an MCP server is not mysterious. At its core:

text
CREATE SERVER
      ↓
REGISTER CAPABILITIES
      ↓
TOOLS
RESOURCES
PROMPTS
      ↓
SELECT TRANSPORT
      ↓
CONNECT CLIENT
      ↓
DISCOVER CAPABILITIES
      ↓
CALL / READ / USE THEM
text
MCP CLIENT
     │
     ▼
QA MCP SERVER
     │
     ├── validate-product-price
     │          TOOL
     │
     ├── qa://testing-guidelines
     │          RESOURCE
     │
     └── review-requirement
                PROMPT
text
When an AI host is added:

HUMAN
  │
  ▼
AI
  │
  ▼
MCP CLIENT
  │
  ▼
MCP SERVER
  │
  ▼
ENGINEERING CAPABILITIES

And when Playwright is added:

HUMAN
  │
  ▼
AI
  │
  ▼
MCP
  │
  ▼
PLAYWRIGHT MCP SERVER
  │
  ▼
PLAYWRIGHT
  │
  ▼
BROWSER
  │
  ▼
APPLICATION

That is the bridge between MCP fundamentals and Agentic AI Testing with Playwright.

Series so far: 1. MCP Fundamentals → 2. MCP Host, Client & Server Deep Dive → 3. MCP Tools, Resources & Prompts → 4. Build Your First MCP Server (this tutorial) → 5. Playwright MCP Fundamentals (next). Previous parts are linked in the recommended articles below.

Playwright Framework Series

View all →
  1. 1Getting Started with Playwright: Installation, Setup, and Your First Test
  2. 2Playwright Locators: The Complete Guide with Real-World Examples
  3. 3Playwright Actions: Complete Guide to Click, Fill, Hover, Keyboard, Mouse & File Upload
  4. 4Playwright Assertions Complete Guide: Web-First Assertions, Auto-Retry & Custom Matchers
  5. 5Playwright Auto Waiting: The Complete Guide with Real-World Examples
  6. 6Playwright Fixtures: The Complete Guide with Real-World Examples
  7. 7Playwright Browser Context & Multiple Tabs: The Complete Guide with Real-World Examples
  8. 8Playwright Authentication & Session Management: Complete Guide with Enterprise Examples
  9. 9Playwright Network Interception & API Mocking: Complete Guide with Real-World Examples
  10. 10Playwright Page Object Model (POM): The Complete Guide with Enterprise Examples
  11. 11Page Object Model with Playwright: A Practical Guide
  12. 12How to Build a Robust Professional Playwright Framework from Scratch (Step-by-Step)
  13. 13Building an Enterprise Playwright Framework from Scratch

API Testing Series

View all →
  1. 1Part 1 : Playwright API Testing Tutorial: Build Enterprise-Level API Automation Framework
  2. 2Part 2: Playwright API Testing Tutorial: Setting Up Project & Sending Your First API Request
  3. 3Part 3: Mastering CRUD Operations in Playwright API Testing
  4. 4Part 4: Authentication in Playwright API Testing (Bearer Token, JWT, API Key & Reusable Fixtures)
  5. 5Part 5: Building an Enterprise-Level Playwright API Automation Framework
  6. 6Part 6: API Models, Schema Validation & Test Data Management in Playwright
  7. 7Part 7: Custom Fixtures, Hooks, Logging & Parallel Execution in Playwright API Testing
  8. 8Part 8: Building a Production-Ready Playwright API Framework (Environment Management, CI/CD, Reporting & Best Practices)
  9. 9Part 9: Advanced Playwright API Testing Techniques for Enterprise Automation
  10. 10Part 10: Building a Complete Enterprise Playwright API Automation Framework (Final Part)
  11. 11Playwright Backend Testing Tutorial – REST API, GraphQL, WebSocket, Kafka, Database & Microservices

Recommended Next Articles