Submit

Mcp Bridge By Appfactor

7 days ago
Point MCP Bridge at any REST, GraphQL, SOAP, or gRPC API. It auto-generates MCP tool definitions with typed schemas, auth, rate limiting, and response processing. Your LLM agents call enterprise APIs through one standard interface.
Overview
", "@type": "SoftwareApplication", "name": "MCP Bridge", "description": "Auto-generate Model Context Protocol tool definitions from any REST, GraphQL, SOAP, or gRPC API. Connect any API to any AI agent without creating long-term technical debt.", "url": "/", "applicationCategory": "DeveloperApplication", "operatingSystem": "Docker, AWS ECS, Azure Container Apps", "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD", "description": "Free trial available, no credit card required" }, "featureList": [ "Auto-generate MCP tools from OpenAPI, GraphQL, WSDL, and gRPC schemas", "Self-hosted Docker container deployment", "Code Mode reduces context window usage by 98%", "Enterprise authentication (OAuth2, AWS Cognito, OIDC)", "Tool curation and response post-processing", "Analytics dashboard with latency, throughput, and token usage metrics", "Semantic tool search with pgvector", "Built in Rust for memory safety and high throughput" ], "softwareRequirements": "Docker, AWS ECS, Azure Container Apps, or any container orchestrator", "inLanguage": "en", "provider": { "@type": "Organization", "name": "AppFactor" }, "availableOnDevice": [ "AWS Marketplace", "Microsoft Azure Marketplace" ] }

[data-accordion-status="active"] .accordion-css__item-bottom { grid-template-rows: 1fr; }

/* Animate Icon */ .accordion-css__item-icon { transition: transform 0.6s cubic-bezier(0.625, 0.05, 0, 1); }

[data-accordion-status="active"] .accordion-css__item-icon { transform: rotate(45deg); }

a { color: inherit; }

@media only screen and (max-width: 999px) { a { cursor: default; } }

*:focus { outline: 0 !important; }

  • { -webkit-tap-highlight-color: transparent; }

/* Для Chrome/Safari/Opera / input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus, input:-webkit-autofill:active { -webkit-box-shadow: 0 0 0 0px var(--dark-grey) inset !important; / Цвет фона / -webkit-text-fill-color: var(--black) !important; / Цвет текста / transition: background-color 5000s ease-in-out 0s; / Долгая transition предотвращает мгновенное изменение стиля */ }

/* Для Firefox */ input:autofill, input:autofill:hover, input:autofill:focus, input:autofill:active { box-shadow: 0 0 0 0px var(--dark-grey) inset !important; -webkit-text-fill-color: var(--black) !important; }

.is__ov-h { -webkit-mask-image: -webkit-radial-gradient(white, black); }

/* To get this shitty padding-bottom/padding-right 75px bug removed */ .wf-design-mode .wf-empty, .wf-editor-mode .wf-empty { padding: 0; }

/* General sizes */ :root { font-size: clamp(12px, 1.1111vw, 20px); }

/* Min Font Size */ @media screen and (max-width: 991px) { :root { font-size: 2.0833333333333335vw; } }

@media screen and (max-width: 479px) { :root { font-size: 4.266666666666667vw; } }

/* Container Max Width */ .container { max-width: 90rem; }

/* Max Font Size */ @media screen and (min-width: 1440px) { :root { font-size: 16px; } }

/* Easings */ :root { --elastic-ease-out: linear( 0, 0.5737 7.6%, 0.8382 11.87%, 0.9463 14.19%, 1.0292 16.54%, 1.0886 18.97%, 1.1258 21.53%, 1.137 22.97%, 1.1424 24.48%, 1.1423 26.1%, 1.1366 27.86%, 1.1165 31.01%, 1.0507 38.62%, 1.0219 42.57%, 0.9995 46.99%, 0.9872 51.63%, 0.9842 58.77%, 1.0011 81.26%, 1 ); --smooth-ease: cubic-bezier(0.32, 0.72, 0, 1); --color-ease: cubic-bezier(0.215, 0.61, 0.355, 1); }

/* Btns */ .btn_txt-hvr { translate: 0 1.9rem; }

.btn_txt-hvr-b { translate: 0 1.9rem; }

.btn_arrow-hvr { translate: -1.9rem 1.9rem; }

.btn_arrow-hvr-b { translate: 1.9rem 1.9rem; }

.btn, .btn-s { transition: background-color 0.65s var(--color-ease); -webkit-tap-highlight-color: transparent; }

.btn-outline, .btn-s-outline, .btn-back { transition: border-color 0.65s var(--color-ease); -webkit-tap-highlight-color: transparent; }

.btn_txt, .btn_txt-hvr, .btn_txt-hvr-b, .btn_arrow, .btn_arrow-hvr, .btn_arrow-hvr-b, .usecases__arrow-hover, .usecases__arrow { transition: translate 0.95s var(--elastic-ease-out); }

/* Use Cases Card And Blog Card*/ .usecases__arrow-hover { translate: -1.3rem 1.3rem; }

.usecases__border, .pl-blog__card { transition: transform 0.65s var(--elastic-ease-out), border-color 0.65s var(--color-ease); }

/* FAQ */ .faq__item { transition: background-color 0.65s var(--color-ease); }

.faq__border { transition: transform 0.95s var(--elastic-ease-out), border-color 0.65s var(--color-ease); }

.faq__answ { transition: max-height 0.95s var(--smooth-ease); }

.faq__line-v { transition: transform 0.95s var(--elastic-ease-out); }

.faq__item.is-act .faq__answ { max-height: 9rem; }

@media screen and (max-width: 479px) { .faq__item.is-act .faq__answ { max-height: 14rem; } }

.faq__item.is-act .faq__border { border-color: rgba(255, 255, 255, 0); }

.faq__item.is-act .faq__line-v { transform: rotate(90deg); }

/* Underline Link */ .underline-link { -webkit-tap-highlight-color: transparent; }

.underline-link::before { content: ""; position: absolute; bottom: -1px; left: 0; width: 100%; height: 1px; background-color: var(--orange); transition: transform 0.75s cubic-bezier(0.625, 0.05, 0, 1); transform-origin: right; transform: scaleX(0) rotate(0.001deg); }

/* Socials */ .footer__social, .bl-main__social { transition: color 0.65s var(--color-ease); }

/* Footer Form */ .footer__input { transition: color 0.65s var(--color-ease), border-color 0.65s var(--color-ease); }

.footer__btn { transition: background-color 0.65s var(--color-ease); }

/* Nav Cases, Nav Comapny */ .nav__dl-wrap, .nav-dd__btm { translate: 0 -2rem; transition: opacity 0.65s var(--color-ease), translate 0.65s var(--smooth-ease); }

.nav__dl-img { transition: opacity 0.65s var(--color-ease); }

.nav__dl-link { transition: opacity 0.65s var(--color-ease), border-color 0.65s var(--color-ease); }

.nav__cases .is-nav, .txt-c-white.underline-link { transition: color 0.65s var(--color-ease); cursor: pointer; }

/* Video */ .cta__video video { position: absolute; top: 50%; left: 50%; min-width: 100%; min-height: 100%; width: auto; height: auto; transform: translate(-50%, -50%); object-fit: cover; }

.swiper-slide.is-f-l, .swiper-slide.is-obs-hiw-l { transition: color 0.65s var(--color-ease), background-color 0.65s var(--color-ease); }

/* Progress Bar Animation */ .features__progress { transition: width 0.5s var(--smooth-ease); }

@keyframes progressAnimation { 0% { width: 0; } 98% { width: 100%; } 100% { width: 0; } }

.features__progress.animate-progress { animation: progressAnimation 9.6s linear forwards; }

.main__vid { border: 3px solid var(--black); border-radius: 12px; }

/* Все hover эффекты в одном медиа-запросе / @media (hover: hover) and (pointer: fine) { / Main Btn */ .btn:is(:hover, :focus-visible) { background: var(--orange); } .btn:is(:hover, :focus-visible) .btn_txt { translate: 0 -1.9rem; } .btn:is(:hover, :focus-visible) .btn_arrow-hvr { translate: 0 0; } .btn:is(:hover, :focus-visible) .btn_arrow { translate: 1.9rem -1.9rem; } .btn:is(:hover, :focus-visible) .btn_txt-hvr { translate: 0 0; }

/* Outline Btn */ .btn-outline:is(:hover, :focus-visible), .btn-back:is(:hover, :focus-visible) { border-color: var(--white-40); } .btn-outline:is(:hover, :focus-visible) .btn_txt, .btn-back:is(:hover, :focus-visible) .btn_txt { translate: 0 -1.9rem; } .btn-outline:is(:hover, :focus-visible) .btn_arrow-hvr, .btn-back:is(:hover, :focus-visible) .btn_arrow-hvr-b { translate: 0 0; } .btn-outline:is(:hover, :focus-visible) .btn_arrow { translate: 1.9rem -1.9rem; } .btn-back:is(:hover, :focus-visible) .btn_arrow { translate: -1.9rem -1.9rem; } .btn-outline:is(:hover, :focus-visible) .btn_txt-hvr, .btn-back:is(:hover, :focus-visible) .btn_txt-hvr-b { translate: 0 0; }

/* Btn Small */ .btn-s:is(:hover, :focus-visible) { background: var(--orange); } .btn-s:is(:hover, :focus-visible) .btn_txt { translate: 0 -1.9rem; } .btn-s:is(:hover, :focus-visible) .btn_txt-hvr { translate: 0 0; }

/* Btn Outline Small */ .btn-s-outline:is(:hover, :focus-visible) { border-color: var(--white-40); } .btn-s-outline:is(:hover, :focus-visible) .btn_txt { translate: 0 -1.9rem; } .btn-s-outline:is(:hover, :focus-visible) .btn_txt-hvr { translate: 0 0; }

/* Use Cases Card And Blog Card */ .usecases__card:is(:hover, :focus-visible) .usecases__border, .pl-blog__card:is(:hover, :focus-visible) .usecases__border { border-color: var(--orange); transform: scaleX(1.01) scaleY(1.01); } .usecases__card:is(:hover, :focus-visible) .usecases__arrow, .pl-blog__card:is(:hover, :focus-visible) .usecases__arrow { translate: 1.3rem -1.3rem; } .usecases__card:is(:hover, :focus-visible) .usecases__arrow-hover, .pl-blog__card:is(:hover, :focus-visible) .usecases__arrow-hover { translate: 0 0; }

/* FAQ */ .faq__item:not(.is-act):is(:hover, :focus-visible) .faq__border { border-color: var(--orange); transform: scaleX(1.004) scaleY(1.015); }

/* Underline Link */ .underline-link:is(:hover, :focus-visible)::before { transform-origin: left; transform: scaleX(1) rotate(0.001deg); }

/* Socials */ .footer__social:is(:hover, :focus-visible), .bl-main__social:is(:hover, :focus-visible) { color: var(--orange); }

/* Footer Form */ .footer__input:is(:hover, :focus-visible) { border-color: var(--orange); } .footer__btn.is-act:is(:hover, :focus-visible) { background: var(--orange); } .footer__btn.is-act:is(:hover, :focus-visible) .btn_txt { translate: 0 -1.9rem; } .footer__btn.is-act:is(:hover, :focus-visible) .btn_txt-hvr { translate: 0 0; }

/* Nav Cases */ .nav__cases:is(:hover, :focus-visible) .is-nav { color: var(--white-40); } .nav__cases:is(:hover, :focus-visible) .nav__dl-wrap { pointer-events: auto; translate: 0 0; opacity: 1; }

/* Nav Company */ .nav-dd:is(:hover, :focus-visible) .txt-c-white.underline-link { color: var(--white-40); } .nav-dd:is(:hover, :focus-visible) .nav-dd__btm { pointer-events: auto; translate: 0 0; opacity: 1; }

/* Slider */ .swiper-slide.is-f-l:not(.swiper-slide-thumb-active):is( :hover, :focus-visible ), .swiper-slide.is-obs-hiw-l:not(.swiper-slide-thumb-active):is( :hover, :focus-visible ) { color: var(--white); background: var(--dark-grey); } } .nav__burger.w--open .nav__bur-clsr { opacity: 1; } .nav__bur-clsr { transition: opacity 0.65s var(--color-ease); }

/* Animate */ [animate] { overflow: hidden; }

.line-wrapper { overflow: hidden; position: relative; width: 100%; display: block; }

.split-line { display: block; position: relative; width: 100%; }

/* Оптимизация производительности */ .split-line { will-change: transform, opacity; backface-visibility: hidden; }

h1 .line-wrapper { padding: 0.08rem 0; /* Добавляем небольшой вертикальный паддинг */ overflow: hidden; }

h1 .split-line { padding: 0.08rem 0; /* Добавляем паддинг и для самих строк */ } @media screen and (min-width: 991px) { .nav__content .underline-link { font-size: max(13px, 0.8125rem); } }

[data-underline-link] { text-decoration: none; position: relative; }

[data-underline-link]::before { content: ""; position: absolute; bottom: -0.0625em; left: 0; width: 100%; height: 0.0625em; background-color: currentColor; transition: transform 0.735s cubic-bezier(0.625, 0.05, 0, 1); transform-origin: right; transform: scaleX(0) rotate(0.001deg); }

@media (hover: hover) and (pointer: fine) { [data-hover]:hover [data-underline-link]::before, [data-underline-link]:hover::before { transform-origin: left; transform: scaleX(1) rotate(0.001deg); } }

/* Animation */ [data-bunny-background-init] :is(.bunny-bg__placeholder, .bunny-bg__loading) { transition: opacity 0.3s linear, visibility 0.3s linear; }

/* Placeholder */ [data-bunny-background-init][data-player-status="playing"] .bunny-bg__placeholder, [data-bunny-background-init][data-player-status="paused"] .bunny-bg__placeholder, [data-bunny-background-init][data-player-activated="true"][data-player-status="ready"] .bunny-bg__placeholder { opacity: 0; visibility: hidden; }

/* Play/Pause */ [data-bunny-background-init][data-player-status="playing"] .bunny-bg__play-svg, [data-bunny-background-init][data-player-status="loading"] .bunny-bg__play-svg { display: none; }

[data-bunny-background-init][data-player-status="playing"] .bunny-bg__pause-svg, [data-bunny-background-init][data-player-status="loading"] .bunny-bg__pause-svg{ display: block; }

/* Loading / [data-bunny-background-init][data-player-status="loading"] .bunny-bg__loading { opacity: 1; visibility: visible; }

MCP/Gradient */ .api-hiv__num, .is-or-2nd { background: linear-gradient(154.84deg, #FF5E19 6.39%, #FF3710 95.79%); }

.is-or-2nd { box-shadow: 0px 0px 14px -3px rgba(255, 73, 20, 0.7); }

.api-code__num, .u-t-color-orange { background: linear-gradient(154.84deg, #FF5E19 6.39%, #FF3710 95.79%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; text-fill-color: transparent; }

.api-main__deploy-card { transition: box-shadow .65s ease; } .api-main__deploy-card:is(:hover, :focus-visible) { box-shadow:0 6px 16px -8px rgba(6,6,6,0.12); } /* Code Tabs */ .code-tab:is(:hover, :focus-visible), .code-copy:is(:hover, :focus-visible) { color: var(--white); }
.code-body pre{margin:0;white-space:pre;} .code-body .kw{color:#FF8A5C;} .code-body .str{color:#9BD89B;} .code-body .num{color:#7EC4F5;} .code-body .cmt{color:rgba(255,255,255,0.35);font-style:italic;} .code-body .var{color:#fff;}

.benef__card:hover .benef__img { filter: grayscale(0%); } .use-cases__control.is-active { color: var(--white); } .use-cases__control.is-active .use-cases__progress-wr { opacity: 1; } .nav { box-shadow: 0px 2px 32px 0px #0000000a; } .hiw__btm { box-shadow: 0px 0px 12px 0px #0000000d; } .main__mid-top { box-shadow: 0px 0px 10.33px 0px #0000000d; } .main__r-ic-wr.is-active { box-shadow: 0px 10px 24px 0px #ff5e191a; } .main__r-ic-wr.is-active .main__r-img { filter: grayscale(0%); }

@media only screen and (max-width: 990px) { .nav__links { box-shadow: 0px 2px 32px 0px #0000000a; }

.nav__mid.is-active .nav__links { opacity:1; pointer-events: auto; transform: translate(0px, 0px); }

/* Анимация бургера в крестик / .nav__mid.is-active .nav-burg__line.is-1 { / Верхняя линия → диагональ сверху */ transform: translate(0%, 0%) rotate(45deg); top: auto; }

.nav__mid.is-active .nav-burg__line.is-2 { /* Средняя линия исчезает */ opacity: 0; }

.nav__mid.is-active .nav-burg__line.is-3 { /* Нижняя линия → диагональ снизу */ transform: translate(0%, 0%) rotate(-45deg); bottom: auto; }

.benef__card.is-act .benef__img { filter: grayscale(0%); }

Connect any API. To any AI agent.

Auto-generate Model Context Protocol tool definitions from any REST, GraphQL, SOAP, or gRPC API. Self-hosted in minutes. No glue code. No rewrites.

Self-hosted · Free trial · No credit card required
OpenAI
Claude
Mistral
Gemini
Any LLM
GraphQL
gRPC
SOAP
OpenAPI
Any API

AI  that delivers

Legacy and most existing APIs weren't designed for a world where the consumer is an LLM. Schemas lack semantic context, tool boundaries are ambiguous, and payloads burn through context windows.

Expose, govern, and optimize LLM, MCP, and API resources through a single point of control — eliminating integration complexity without creating and maintaining hundreds of individual MCP servers.

for developers

Ship an MCP server in 2 minutes. Not 2 weeks.

Stop writing tool definitions by hand. Point MCP Bridge at any schema URL and every operation becomes a fully typed, annotated MCP tool — ready for Claude, GPT, Gemini, or any MCP-compatible client.

# Pull and run MCP Bridge
$ docker run -d <br/>  --name mcp-bridge <br/>  -p 8080:8080 <br/>  -v ./bridge.yaml:/app/config.yaml <br/>  appfactor/mcp-bridge:latest

# Point any MCP client at the endpoint
$ curl https://localhost:8080/mcp/tools
42 tools generated · ready

apis:
  - name: "payments"
    protocol: "rest"
    schema: "https://api.acme.io/openapi.yaml"
    auth:
      type: "oauth2"
      flow: "client_credentials"
    code_mode: true     # 98% less context

observability:
  otel: true
  log_level: "info"

# Auto-generated tools, ready for any LLM
tools_generated: 42
protocols: [rest, graphql]
annotations:
 read_only: 28
 idempotent: 31
 destructive: 4
avg_tokens_per_tool: 487
code_mode_tokens: 960  # vs ~48,000 raw

Schema-driven

OpenAPI 3, GraphQL introspection, WSDL, and .proto files — all parsed automatically.

Self-hosted

Docker container on AWS ECS, Azure Container Apps, or any orchestrator. Your data never leaves your network.

Built in Rust

Memory-safe, high-throughput, production-ready. Zero external SaaS dependencies at runtime.

How it works

From API to AI-ready tool in four steps.

1

Import API schemas

Provide a schema via URL, paste content, or upload files. Supports OpenAPI (JSON/YAML), GraphQL introspection, WSDL, and gRPC (server reflection or .proto files).

2

Auto-generate MCP tools

Each operation becomes a fully described MCP tool with typed input/output schemas, parameter mappings, behavioural annotations, and documentation.

3

Execute at runtime

MCP Bridge validates inputs, maps parameters, handles authentication, and forwards requests to the backend. Responses are post-processed to reduce token waste.

4

Scale with Code Mode

For large APIs, 3 meta-tools replace the full catalog — cutting context window usage by ~98%. The LLM orchestrates calls via a secure Boa sandbox.

Not a gateway

Built for AI agents, not just HTTP traffic.

API gateways route HTTP requests. MCP Bridge does something fundamentally different — it translates APIs into semantically rich tool definitions LLMs can reason about, select correctly, and call efficiently.

It handles what gateways were never designed for: tool curation, response post-processing to reduce token waste, context window management, and AI-specific observability across latency, throughput, token usage, and error rates.

Tool generation
Semantic context
Token optimization
Protocols
AI observability
Tool discovery
API Gateway
API Gateway
None
N/A
REST only
Basic logs
Static catalog
MCP Bridge
Automatic
Annotations + schemas
Post-processing pipeline
REST · GraphQL · SOAP · gRPC
Latency · tokens · errors · O-Tel
Semantic search + pgvector
Tool generation
MCP Bridge
Automatic
API Gateway
Manual
Semantic context
MCP Bridge
Annotations + schemas
API Gateway
None
Tool generation
MCP Bridge
Post-processing pipeline
API Gateway
N/A
Token optimization
MCP Bridge
REST · GraphQL · SOAP · gRPC
API Gateway
REST only
Tool generation
MCP Bridge
Latency · tokens · errors · O-Tel
API Gateway
Basic logs
Tool generation
MCP Bridge
Semantic search + pgvector
API Gateway
Static catalog

Code Mode

~98%  less

Context window usage

Three meta-tools replace hundreds of individual tool definitions. The LLM discovers tools on demand and orchestrates calls via JavaScript in a secure Boa sandbox with 30-second timeout — same capabilities, a fraction of the token cost.

Standard — 100+ tool definitions

~48,000 tokens

Code Mode — 3 meta-tools

~960 tokens

Capabilities

Enterprise-ready, on day one.

Tool curation

Enable, rename, edit descriptions, customize parameter mappings, and configure per-tool response processing.

Response post-processing

Per-tool declarative rules — unwrap, select, exclude, limit, sort, flatten, aggregate — or custom JavaScript in a sandbox.

Enterprise auth

Bearer, Basic, API Key, OAuth2, AWS Cognito SRP. OIDC for the web UI with Entra ID, Keycloak, Auth0, Okta.

Analytics dashboard

Latency, throughput, per-tool and per-API metrics, token usage breakdowns, error rates. O-Tel in Enterprise.

Tool annotations

Read-only, destructive, idempotent, and open-world hints auto-inferred from API semantics. Editable per tool.

Hybrid search with full-text, trigram fuzzy matching, and optional vector similarity via pgvector and HNSW.

Self-hosted

Docker container on AWS ECS, Azure Container Apps, or any orchestrator. Zero external SaaS dependencies.

Reliability

Per-API token bucket rate limiting, exponential backoff with jitter, configurable retry policies, health checks.

Who it's for

Built for the teams making AI work in production.

Platform Engineering

Expose internal APIs to AI agents

Without writing or maintaining MCP adapters for each service. Import schemas, configure auth, and expose governed tools through a single control plane.

AI Engineers

A managed tool layer for agents

Build agents that call enterprise APIs with authentication, rate limiting, response post-processing, and observability built in — not bolted on.

Enterprise Organizations

Bridge your API portfolio to MCP

Adopt MCP as a standard. Connect your existing API landscape to LLM clients quickly and securely, without refactoring services.

Give your AI agents the data access they need.

Available on AWS and Azure Marketplace. Tiers from evaluation to enterprise-wide deployment.

Self-hosted · Free trial · No credit card required

document.querySelectorAll('.code-tab').forEach(tab => { tab.addEventListener('click', () => { const surface = tab.closest('.code-surface'); surface.querySelectorAll('.code-tab').forEach(t => t.classList.toggle('active', t === tab)); surface.querySelectorAll('.code-pane').forEach(p => p.classList.toggle('active', p.id === tab.dataset.pane)); }); });

document.querySelectorAll('[data-copy]').forEach(btn => { btn.addEventListener('click', () => { const surface = btn.closest('.code-surface'); const active = surface.querySelector('.code-pane.active'); if (!active) return; navigator.clipboard?.writeText(active.innerText.trim()); const orig = btn.textContent; btn.textContent = 'Copied'; setTimeout(() => btn.textContent = orig, 1600); }); });

// --- АНИМАЦИЯ ЛИНИЙ 1 (один раз) --- const lines1Timeline = gsap.timeline();

const line1 = prepareLine(".an-l-1"); const line2 = prepareLine(".an-l-2"); const line3 = prepareLine(".an-l-3"); const line4 = prepareLine(".an-l-4");

if (line1) { lines1Timeline.to( line1, { strokeDashoffset: 0, duration: 1, ease: "power3.out", }, 0 ); }

if (line2) { lines1Timeline.to( line2, { strokeDashoffset: 0, duration: 1, ease: "power3.out", }, 0.2 ); }

if (line3) { lines1Timeline.to( line3, { strokeDashoffset: 0, duration: 1, ease: "power3.out", }, 0.4 ); }

if (line4) { lines1Timeline.to( line4, { strokeDashoffset: 0, duration: 1, ease: "power3.out", }, 0.6 ); }

// --- АНИМАЦИЯ КРУГОВ 1 (бесконечный цикл, 2 сек каждый) --- const circles1Timeline = gsap.timeline({ repeat: -1, repeatDelay: 0, paused: true, });

// последний старт 0.6 + 2 сек движения = 2.6 const circles1Duration = 2.6;

const path1 = document.querySelector(".an-l-1"); const path2 = document.querySelector(".an-l-2"); const path3 = document.querySelector(".an-l-3"); const path4 = document.querySelector(".an-l-4");

circles1Timeline.set( [".cir-1", ".cir-2", ".cir-3", ".cir-4"], { opacity: 1 }, 0 );

circles1Timeline .to( ".cir-1", { duration: 2, ease: "power3.out", motionPath: { path: path1, align: path1, alignOrigin: [0.5, 0.5], start: 0, end: 1, }, }, 0 ) .set(".cir-1", { opacity: 0 }, 0 + 2);

circles1Timeline .to( ".cir-2", { duration: 2, ease: "power3.out", motionPath: { path: path2, align: path2, alignOrigin: [0.5, 0.5], start: 0, end: 1, }, }, 0.2 ) .set(".cir-2", { opacity: 0 }, 0.2 + 2);

circles1Timeline .to( ".cir-3", { duration: 2, ease: "power3.out", motionPath: { path: path3, align: path3, alignOrigin: [0.5, 0.5], start: 0, end: 1, }, }, 0.4 ) .set(".cir-3", { opacity: 0 }, 0.4 + 2);

circles1Timeline .to( ".cir-4", { duration: 2, ease: "power3.out", motionPath: { path: path4, align: path4, alignOrigin: [0.5, 0.5], start: 0, end: 1, }, }, 0.6 ) .set(".cir-4", { opacity: 0 }, 0.6 + 2);

// --- АНИМАЦИЯ ЛИНИЙ 2 (один раз, 1 c каждая) --- const lines2Timeline = gsap.timeline({ paused: true }); const rightItems = document.querySelectorAll(".main__r-wr .main__r-ic-wr");

const addActiveClass = (index) => { if (!rightItems[index]) return; rightItems[index].classList.add("is-active"); };

const line5 = prepareLine(".an-l-5"); const line6 = prepareLine(".an-l-6"); const line7 = prepareLine(".an-l-7"); const line8 = prepareLine(".an-l-8"); const line9 = prepareLine(".an-l-9");

// an-l-5 + 1-й блок, t=0 if (line5) { lines2Timeline.to( line5, { strokeDashoffset: 0, duration: 1, ease: "power3.out", onStart: () => addActiveClass(0), }, 0 ); } else { lines2Timeline.add(() => addActiveClass(0), 0); }

// an-l-6 + 2-й блок, t=0.2 if (line6) { lines2Timeline.to( line6, { strokeDashoffset: 0, duration: 1, ease: "power3.out", onStart: () => addActiveClass(1), }, 0.2 ); } else { lines2Timeline.add(() => addActiveClass(1), 0.2); }

// an-l-7 + 3-й блок, t=0.4 if (line7) { lines2Timeline.to( line7, { strokeDashoffset: 0, duration: 1, ease: "power3.out", onStart: () => addActiveClass(2), }, 0.4 ); } else { lines2Timeline.add(() => addActiveClass(2), 0.4); }

// an-l-8 + 4-й блок, t=0.6 if (line8) { lines2Timeline.to( line8, { strokeDashoffset: 0, duration: 1, ease: "power3.out", onStart: () => addActiveClass(3), }, 0.6 ); } else { lines2Timeline.add(() => addActiveClass(3), 0.6); }

// an-l-9 + 5-й блок, t=0.8 if (line9) { lines2Timeline.to( line9, { strokeDashoffset: 0, duration: 1, ease: "power3.out", onStart: () => addActiveClass(4), }, 0.8 ); } else { lines2Timeline.add(() => addActiveClass(4), 0.8); }

// --- АНИМАЦИЯ КРУГОВ 2 (цикл, 2 c каждый, 5 кругов) --- const circles2Timeline = gsap.timeline({ repeat: -1, repeatDelay: 0, paused: true, });

const path5 = document.querySelector(".an-l-5"); const path6 = document.querySelector(".an-l-6"); const path7 = document.querySelector(".an-l-7"); const path8 = document.querySelector(".an-l-8"); const path9 = document.querySelector(".an-l-9");

circles2Timeline.set( [".cir-5", ".cir-6", ".cir-7", ".cir-8", ".cir-9"], { opacity: 1 }, 0 );

// cir-5 по an-l-5, t=0 circles2Timeline .to( ".cir-5", { duration: 2, ease: "power3.out", motionPath: { path: path5, align: path5, alignOrigin: [0.5, 0.5], start: 0, end: 1, }, }, 0 ) .set(".cir-5", { opacity: 0 }, 2);

// cir-6 по an-l-6, t=0.2 circles2Timeline .to( ".cir-6", { duration: 2, ease: "power3.out", motionPath: { path: path6, align: path6, alignOrigin: [0.5, 0.5], start: 0, end: 1, }, }, 0.2 ) .set(".cir-6", { opacity: 0 }, 2.2);

// cir-7 по an-l-7, t=0.4 circles2Timeline .to( ".cir-7", { duration: 2, ease: "power3.out", motionPath: { path: path7, align: path7, alignOrigin: [0.5, 0.5], start: 0, end: 1, }, }, 0.4 ) .set(".cir-7", { opacity: 0 }, 2.4);

// cir-8 по an-l-8, t=0.6 circles2Timeline .to( ".cir-8", { duration: 2, ease: "power3.out", motionPath: { path: path8, align: path8, alignOrigin: [0.5, 0.5], start: 0, end: 1, }, }, 0.6 ) .set(".cir-8", { opacity: 0 }, 2.6);

// cir-9 по an-l-9, t=0.8 circles2Timeline .to( ".cir-9", { duration: 2, ease: "power3.out", motionPath: { path: path9, align: path9, alignOrigin: [0.5, 0.5], start: 0, end: 1, }, }, 0.8 ) .set(".cir-9", { opacity: 0 }, 2.8);

// --- ФЛОУ ---

let secondStageStarted = false;

// После окончания линий 1 запускаем круги 1 lines1Timeline.eventCallback("onComplete", () => { circles1Timeline.restart(true); });

// После окончания ПЕРВОГО цикла кругов 1 запускаем линии 2, // а после завершения линий 2 — бесконечные круги 2 circles1Timeline.eventCallback("onRepeat", () => { if (secondStageStarted) return; secondStageStarted = true;

lines2Timeline.restart(true);

lines2Timeline.eventCallback("onComplete", () => {
  circles2Timeline.restart(true);
});

}); });

© 2025 MCP.so. All rights reserved.

Build with ShipAny.

Mcp Bridge By Appfactor MCP Server