# Directory Structure
```
├── .eslintrc.json
├── .gitignore
├── app
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── components
│ ├── Base.tsx
│ └── ui
│ ├── accordion.tsx
│ └── button.tsx
├── components.json
├── functions
│ └── get_geo.ts
├── lib
│ └── utils.ts
├── LICENSE
├── mcp-server
│ ├── .gitignore
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── next.config.mjs
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── public
│ └── next.svg
├── README_zh-CN.md
├── README.md
├── tailwind.config.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
```json
{
"extends": "next/core-web-vitals"
}
```
--------------------------------------------------------------------------------
/mcp-server/.gitignore:
--------------------------------------------------------------------------------
```
# Dependencies
node_modules/
# Build output
dist/
# Environment variables
.env
.env.local
.env.*
# NPM
.npmrc
.npmrc.local
.npmrc.*
.npm
# IDE
.idea/
.vscode/
*.sublime-*
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# System files
.DS_Store
Thumbs.db
test.ts
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
# Tencent Cloud Edge Functions
.env
.edgeone
edgeone.json
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
# EdgeOne Pages MCP: Geo Location Service
This project demonstrates how to use EdgeOne Pages Functions to retrieve user geolocation information and integrate it with large language models through MCP (Model Context Protocol).
## Demo

## Deploy
[](https://edgeone.ai/pages/new?template=mcp-geo)
More Templates: [EdgeOne Pages](https://edgeone.ai/pages/templates)
## Components
### 1. EdgeOne Pages Functions: Geolocation
The project includes an EdgeOne Pages Function that retrieves user geolocation information:
* Uses the EdgeOne request context to access geolocation data
* Returns location information in a JSON format
* Located in `functions/get_geo.ts`
### 2. MCP Server Integration
The MCP server component provides an interface for large language models to access geolocation data:
* Implements the Model Context Protocol (MCP)
* Exposes a `get_geolocation` tool that can be used by AI models
* Uses the EdgeOne Pages Function to fetch geolocation data
* Located in `mcp-server/index.ts`
## MCP Configuration
To use the MCP server with large language models, add the following configuration:
```json
{
"mcpServers": {
"edgeone-geo-mcp-server": {
"command": "tsx",
"args": ["path/to/mcp-server/index.ts"]
}
}
}
```
## Learn More
* [EdgeOne Pages](https://edgeone.ai/products/pages)
* [EdgeOne Pages Functions documentation](https://edgeone.ai/document/162227908259442688)
* [Model Context Protocol (MCP)](https://modelcontextprotocol.github.io) - Learn about integrating AI models with external tools and services
```
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
```
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
};
export default nextConfig;
```
--------------------------------------------------------------------------------
/app/page.tsx:
--------------------------------------------------------------------------------
```typescript
import { Base } from '@/components/Base';
export default function Home() {
return (
<main>
<Base />
</main>
);
}
```
--------------------------------------------------------------------------------
/postcss.config.mjs:
--------------------------------------------------------------------------------
```
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};
export default config;
```
--------------------------------------------------------------------------------
/lib/utils.ts:
--------------------------------------------------------------------------------
```typescript
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
```
--------------------------------------------------------------------------------
/functions/get_geo.ts:
--------------------------------------------------------------------------------
```typescript
export function onRequest({ request }: { request: any }) {
const geo = request.eo.geo;
const res = JSON.stringify({
geo: geo,
});
return new Response(res, {
headers: {
'content-type': 'application/json; charset=UTF-8',
'Access-Control-Allow-Origin': '*',
},
});
}
```
--------------------------------------------------------------------------------
/mcp-server/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "mcp-geo-server",
"version": "0.0.1",
"description": "A tool to get user geolocation information",
"main": "index.ts",
"type": "module",
"scripts": {},
"keywords": [],
"author": "EdgeOne Pages",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.7.0",
"zod": "^3.24.2"
}
}
```
--------------------------------------------------------------------------------
/mcp-server/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
"target": "ES2020",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./dist",
"rootDir": "./",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["index.ts"],
"exclude": ["node_modules", "dist"]
}
```
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
```json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
```
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
```typescript
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "EdgeOne Pages MCP: Geo Location Service",
description: "A demo project showcasing EdgeOne Pages Functions for geolocation information and MCP integration",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules", "mcp-server"]
}
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "functions-geo",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"postinstall": "cd mcp-server && npm install"
},
"dependencies": {
"@radix-ui/react-accordion": "^1.2.0",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-slot": "^1.1.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"lucide-react": "^0.438.0",
"next": "14.2.5",
"react": "^18",
"react-dom": "^18",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7",
"@jridgewell/gen-mapping": "0.3.5"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.2.5",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
}
}
```
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
```
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
```
--------------------------------------------------------------------------------
/mcp-server/index.ts:
--------------------------------------------------------------------------------
```typescript
#!/usr/bin/env node
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new McpServer({
name: 'edgeone-geo-mcp-server',
version: '1.0.0',
description: 'An MCP service for getting user geolocation information',
});
const handleApiError = (error: any) => {
console.error('API Error:', error);
const errorMessage = error.message || 'Unknown error occurred';
return {
content: [
{
type: 'text' as const,
text: `Error: ${errorMessage}`,
},
],
isError: true,
};
};
export async function getGeoLocation(): Promise<any> {
try {
const res = await fetch('https://mcp-geo.edgeone.app/get_geo');
if (!res.ok) {
throw new Error(`HTTP error: ${res.status} ${res.statusText}`);
}
return await res.json();
} catch (error) {
console.error('Failed to get geolocation:', error);
throw error;
}
}
server.tool(
'get_geolocation',
"Get the user's geolocation information",
{},
async () => {
try {
const geoData = await getGeoLocation();
return {
content: [
{
type: 'text' as const,
text: JSON.stringify(geoData, null, 2),
},
],
};
} catch (e) {
return handleApiError(e);
}
}
);
console.log('Starting edgeone-geo-mcp-server...');
const transport = new StdioServerTransport();
await server.connect(transport);
console.log('edgeone-geo-mcp-server started successfully!');
```
--------------------------------------------------------------------------------
/components/ui/button.tsx:
--------------------------------------------------------------------------------
```typescript
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline:
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button, buttonVariants }
```
--------------------------------------------------------------------------------
/components/ui/accordion.tsx:
--------------------------------------------------------------------------------
```typescript
"use client"
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { ChevronDownIcon } from "@radix-ui/react-icons"
import { cn } from "@/lib/utils"
const Accordion = AccordionPrimitive.Root
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item
ref={ref}
className={cn("border-b", className)}
{...props}
/>
))
AccordionItem.displayName = "AccordionItem"
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
{children}
<ChevronDownIcon className="w-4 h-4 transition-transform duration-200 shrink-0 text-muted-foreground" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
{...props}
>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
</AccordionPrimitive.Content>
))
AccordionContent.displayName = AccordionPrimitive.Content.displayName
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
```
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
}
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
```
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
```typescript
import type { Config } from "tailwindcss";
const config: Config = {
darkMode: ["class"],
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))'
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)'
},
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))'
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))'
},
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))'
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))'
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))'
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))'
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))'
},
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
chart: {
'1': 'hsl(var(--chart-1))',
'2': 'hsl(var(--chart-2))',
'3': 'hsl(var(--chart-3))',
'4': 'hsl(var(--chart-4))',
'5': 'hsl(var(--chart-5))'
}
},
keyframes: {
'accordion-down': {
from: {
height: '0'
},
to: {
height: 'var(--radix-accordion-content-height)'
}
},
'accordion-up': {
from: {
height: 'var(--radix-accordion-content-height)'
},
to: {
height: '0'
}
}
},
animation: {
'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out'
}
}
},
plugins: [require("tailwindcss-animate")],
};
export default config;
```
--------------------------------------------------------------------------------
/components/Base.tsx:
--------------------------------------------------------------------------------
```typescript
import React from 'react';
export const Base = () => {
return (
<div className="min-h-screen bg-gradient-to-b from-gray-50 to-gray-100 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-4xl mx-auto">
<div className="text-center">
<h1 className="text-4xl font-bold text-gray-900 mb-4">
EdgeOne Pages MCP: Geo Location Service
</h1>
<p className="text-xl text-gray-600 mb-8">
A geolocation service example demonstrating how to obtain user
location information in EdgeOne Pages and interact with AI models
through the MCP protocol.
</p>
</div>
{/* Project Overview */}
<div className="bg-white rounded-lg shadow-lg p-6 mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
Project Overview
</h2>
<p className="text-gray-600 mb-4">
In modern web applications, obtaining user geolocation information
is a common requirement. This project demonstrates how to:
</p>
<ul className="list-disc list-inside text-gray-600 space-y-2 mb-4">
<li>
Securely obtain user geolocation using EdgeOne Pages Functions
</li>
<li>
Enable AI models to access location data through the MCP protocol
</li>
<li>Elegantly display location information in the frontend</li>
</ul>
</div>
{/* Core Features */}
<div className="bg-white rounded-lg shadow-lg p-6 mb-8">
<h2 className="text-2xl font-semibold text-gray-900 mb-4">
Core Features
</h2>
<div className="grid md:grid-cols-2 gap-6">
<div className="border border-gray-200 rounded-lg p-4">
<h3 className="text-lg font-medium text-gray-900 mb-2">
EdgeOne Pages Functions
</h3>
<ul className="text-gray-600 space-y-2">
<li>
• Automatically retrieve visitor's geolocation information
</li>
<li>
• Includes detailed data about country, region, city, etc.
</li>
<li>
• Precise positioning through EdgeOne's global node network
</li>
<li>• Returns standardized JSON format data</li>
</ul>
</div>
<div className="border border-gray-200 rounded-lg p-4">
<h3 className="text-lg font-medium text-gray-900 mb-2">
MCP Protocol Integration
</h3>
<ul className="text-gray-600 space-y-2">
<li>• Implements Model Context Protocol standard</li>
<li>• Provides get_geolocation tool interface</li>
<li>
• Supports real-time AI model calls to geolocation service
</li>
<li>• Convenient server-side integration solution</li>
</ul>
</div>
</div>
</div>
{/* Quick Start */}
<div className="text-center space-y-4">
<a
href="https://edgeone.ai/pages/new?template=mcp-geo"
target="_blank"
rel="noopener noreferrer"
aria-label="Deploy your own instance of the MCP Geo Location Service"
className="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 mr-4"
>
Deploy Now
</a>
<a
href="https://edgeone.ai/pages/templates"
target="_blank"
rel="noopener noreferrer"
aria-label="View more EdgeOne Pages templates"
className="inline-flex items-center px-6 py-3 border border-gray-300 text-base font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50"
>
View More Templates
</a>
</div>
</div>
</div>
);
};
```